C言語なら俺に聞け(入門編)Part 115

1名無しさん@Next2ch:2013/05/16(木) 13:55:14.62 ID:MGNiMjNi

C言語の入門者向け解説スレッドです。

★前スレ
C言語なら俺に聞け(入門編)Part 114
http://toro.2ch.net/test/read.cgi/tech/1366573639/
★過去スレ
http://makimo.to:8000/cgi-bin/search/search.cgi?q=%82b%8C%BE%8C%EA%82%C8%82%E7%89%B4%82%C9%95%B7%82%AF&andor=AND&sf=0&H=&view=table&D=tech&shw=5000
★教えて欲しいのではなく宿題を丸投げしたいだけなら
  ↓宿題スレ↓へ行ってください。
C/C++の宿題片付けます 164代目
http://toro.2ch.net/test/read.cgi/tech/1364700745/
★C++言語については避けてください。C++対応明記スレへどうぞ。
★分からない事をなるべく詳しく書いて下さい。
★ソースコードを晒すと答えやすくなるかもしれません。
  # 抜粋/整形厳禁、コンパイラに渡したソースをそのまま貼ること。
  # サイズが大きい場合はアップローダ等を利用してください。
http://codepad.org/
http://ideone.com/
★開発環境や動作環境も晒すと答えが早いかもしれません。
★質問者は最初にその質問をした時のレス番号を名前欄に書いて下さい。

2名無しさん@Next2ch:2015/03/05(木) 01:28:26.29 ID:W8pFEDqo

< `∀´>ニダー

3名無しさん@Next2ch:2015/03/18(水) 11:55:24.33 ID:SMi9Fbq0

Cプリプロセッサの#(文字列化)が期待通りに展開出来ない理由と対策

test1.c
#define STR(x) #x
STR(hoge)
を展開(cc -E test.c)すると
"hoge"
と期待通りに展開できるが、
test2.c
#define STR(x) #x
#define S hoge
STR(S)
と展開すると
"S"
と期待通りの展開はされない。これからその理由と対策について述べる。

規格書に準じてCプリプロセッサがどのように展開を行っていくか追跡してみよう。
(1)-(5)まではJISX3010の6.10.3から引用する。

(1)
関数形式マクロ名の次の前処理字句として(が現れたときには,マクロ名からこの(前
処理字句に対応する)前処理字句までの前処理字句列を,この定義内の置換要素並び
で置き換える(マクロ呼び出し)
-> STR(S)をその定義によって置き換える

(2)
最も外側の括弧によって囲まれた前処理字句の列は,関数形式マクロの実引数の並び
を形成する。
-> Sが実引数

4名無しさん@Next2ch:2015/03/18(水) 11:56:54.54 ID:SMi9Fbq0

続き

(3)
関数形式マクロの実引数を識別した後,実引数置換を行う。実引数の中に含まれるす
べてのマクロの展開後,置換要素並びの中の仮引数を対応する実引数で置き換える。
ただし,次の仮引数は除く
- #前処理字句又は##前処理字句が前にある仮引数
- ##前処理字句が後に続く仮引数
-> 実引数Sはマクロ展開されない

(4)
置換要素並びの中で,仮引数の直前に#前処理字句がある場合,対応する実引数の前
処理字句列のつづりを含んだ一つの単純文字列リテラル前処理字句によって,#前
処理字句と仮引数を置き換える。
-> "S"に展開される。

STR(S)を"hoge"に展開するにはどうすれば良いか?
#define STR(x) #x
#define STR(x) STR_(x)
#define S hoge
STR(S)
と二段階にすれば良い。

どのように展開されるか、追跡しよう。(2)までは同じだ。
-> 実引数Sがhogeに展開され、STR(S)はSTR_(hoge)に置き換えられる。

(5)
置換要素並び中のすべての仮引数を置き換え、更に#演算子及び##演算子の処理を
行った後,すべてのプレースマーカー前処理字句を削除する。その後,更に置き換
えるべきマクロ名があるかどうかを調べるために,ソースファイル上のその後のす
べての前処理字句と共にその結果の前処理字句を再走査する。
-> STR_(hoge)を再置き換えする (以下説明略)

5名無しさん@Next2ch:2015/03/18(水) 12:51:16.33 ID:SMi9Fbq0

>>4
訂正

(3)
関数形式マクロの実引数を識別した後,実引数置換を行う。実引数の中に含まれるす
べてのマクロの展開後,置換要素並びの中の仮引数を対応する実引数で置き換える。
ただし,次の仮引数は除く
- #前処理字句又は##前処理字句が前にある仮引数
- ##前処理字句が後に続く仮引数
-> 実引数Sはマクロ展開されない

(4)
置換要素並びの中で,仮引数の直前に#前処理字句がある場合,対応する実引数の前
処理字句列のつづりを含んだ一つの単純文字列リテラル前処理字句によって,#前
処理字句と仮引数を置き換える。
-> "S"に展開される。

STR(S)を"hoge"に展開するにはどうすれば良いか?
#define STR_(x) #x
#define STR(x) STR_(x)
#define S hoge
STR(S)
と二段階にすれば良い。

どのように展開されるか、追跡しよう。(2)までは同じだ。
(3)'
-> 実引数Sがhogeに展開され、STR(S)はSTR_(hoge)に置き換えられる。

(5)
置換要素並び中のすべての仮引数を置き換え、更に#演算子及び##演算子の処理を
行った後,すべてのプレースマーカー前処理字句を削除する。その後,更に置き換
えるべきマクロ名があるかどうかを調べるために,ソースファイル上のその後のす
べての前処理字句と共にその結果の前処理字句を再走査する。
-> STR_(hoge)を再置き換えする (以下説明略)

6名無しさん@Next2ch:2015/03/18(水) 12:51:57.44 ID:mnTULdg5

スレ番号をnetからの続きにするのやめようよ - Next2ch
http://next2ch.net/tech/1424541553

7片山博文MZ◆NveQN6OtcI:2015/03/18(水) 19:23:47.32 ID:rd0I/v2M

ちょうどマクロ展開の実装をするところだった。
ありがとう。参考にするよ。

8名無しさん@Next2ch:2015/03/22(日) 19:58:26.26 ID:hZbXpMvg

http://peace.2ch.net/test/read.cgi/tech/1408962564/577

9名無しさん@Next2ch:2015/11/06(金) 07:31:00.12 ID:n3XLiNkH

・独学で勉強中(趣味程度) linux14.04LTS メモ帳で作成
・何度書き直しても同じエラーが出る

・コード
#include <stdio.h>
int main(void)
{
struct TEST{
int figure;
short value;
char letter;
};
TEST test;

test.figure=100;
test.value=200;
test.letter='A';

printf("%d\n",test.figure);
printf("%d\n",test.value);
printf("%c\n",test.letter);

return 0;
}

・エラー
study01.c: In function ‘main’:
study01.c:9:2: error: unknown type name ‘TEST’
TEST test;
^
study01.c:11:6: error: request for member ‘figure’ in something not a structure or union
test.figure=100;
^
study01.c:12:6: error: request for member ‘value’ in something not a structure or union
test.value=200;
^
study01.c:13:6: error: request for member ‘letter’ in something not a structure or union
test.letter='A';
^
study01.c:15:20: error: request for member ‘figure’ in something not a structure or union
printf("%d\n",test.figure);
^
study01.c:16:20: error: request for member ‘value’ in something not a structure or union
printf("%d\n",test.value);
^
study01.c:17:20: error: request for member ‘letter’ in something not a structure or union
printf("%c\n",test.letter);
^


10名無しさん@Next2ch:2015/11/06(金) 07:31:51.57 ID:n3XLiNkH

訂正 ubuntu14.04LTS

11名無しさん@Next2ch:2015/11/06(金) 08:11:55.85 ID:K+BOG2oz

9行目を
struct TEST test;
にしたらいい

12:2015/11/06(金) 08:21:02.78 ID:n3XLiNkH

なるほど
構造体のTEST型のtest変数を作る時にもstructは必要なのかぁ

ありがとう

13片山博文MZ◆NveQN6OtcI:2018/01/10(水) 21:22:29.76 ID:x8C6rZHn

typedefするか、C++にすれば以降、structは書かなくてよくなるぜ。

14名無しさん@Next2ch:2022/09/24(土) 23:33:44.82 ID:JDUknmhx

むしろ型自体を構造体でローカル定義してたりすんの?


レスを書き込む