#define name 置換テキスト
関数と違う点
- マクロはコンパイル時に置換される。
#define dprint(a) printf("result = %g\n", a)
dprint(a);//コンパイル後はprintf("result = %g\n", a);に置換
言い方は悪いが、普通のコードに置換されている。
そのため関数のようなオーバーヘッドがない。
- 型指定がない。
有名な間違い
#define max(A,B) ((A) > (B) ? (A) : (B))
max(i++,j++) //間違い
インクリメントが複数回実効される。
#define square(x) x*x //間違い
square(z+1)だと
z+1*z+1=z+z+1=2z+1になってしまう。
正しくは、
#define square(x) ((x)*(x))
#記号(パラメータを実引数に置換)
#記号はパラメータを実引数に変換後、""で囲んでくれる。
#define dprint(expr) printf(#expr "= %g\n", expr)
dprint(x/y);
↓
printf("x/y""= %g\n",x/y);
↓
printf("x/y= %g\n",x/y);
##記号(文字列結合、引数呼び出し禁止)
#define cat(a,b) a ## b
cat(1,2);
##の隣の空白は削除されて文字列12になる。
また##のまわりでは引数展開できない(正確には不定)
つまり、
間違った予測では以下のようになる。
cat(cat(1,2),3);
↓
cat(1,2) ## 3
↓
(1 ## 2) ## 3
↓
12 ## 3
↓
123
実際は##のまわりでは引数展開が不定なので、
cat(cat(1,2),3);
↓
cat(1,2) ## 3 //cat(1,2)は展開されない
↓
cat(1,2)3
##を使わなければ可能
#define xcat(x,y) cat(x,y)
xcat(xcat(1,2),3);
↓
123
0 件のコメント:
コメントを投稿