次のコードの出力は 8 24 32 です。8 と 24 の背後にあるロジックは理解していますが、32 は私には非常に奇妙に思えます。なぜ32と表示されるのか誰か説明できますか?
#define cube(x) x*x*x
void main()
{
printf("%d ",cube(2));
printf("%d ",16+cube(2));
printf("%d ",16/cube(2));
}
次のコードの出力は 8 24 32 です。8 と 24 の背後にあるロジックは理解していますが、32 は私には非常に奇妙に思えます。なぜ32と表示されるのか誰か説明できますか?
#define cube(x) x*x*x
void main()
{
printf("%d ",cube(2));
printf("%d ",16+cube(2));
printf("%d ",16/cube(2));
}
最後printf
は次のように変換されます:
printf("%d ",16/2 * 2 * 2);
そのため、すべてのマクロを括弧で囲む必要があります。
#define cube(x) ((x)*(x)*(x))
または、関数を使用し、コンパイラを信頼してインライン化します。関数はほとんど常に優れています。
マクロは、テキスト1のコンパイル時の置換にすぎません。したがって、C プリプロセッサは次の行を変更します。
printf("%d ",16/cube(2));
この行に:
printf("%d ", 16/2*2*2);
このテキスト置換が完了すると、コンパイラは式を調べます。これにより、次の評価が得られます。
// 16/2 is evaluated first because '/' has the same precedence as '*',
// so the tie is broken by left-to-ride order:
printf("%d ", 8*2*2);
// Then each of the '*' operators is evaluated in turn:
printf("%d ", 16*2);
printf("%d ", 32);
一般に、マクロ パラメーターの各使用とマクロ定義全体を括弧で囲んで、マクロ内の式の解釈方法が演算子の優先順位によって変更されないようにすることをお勧めします。
#define cube(x) ((x)*(x)*(x))
キューブがマクロではなく関数である場合、関数は引数が渡される前に完全にコンパイルされるため、結果が異なることに注意してください。
int cube (int x)
{
return x*x*x;
}
…
printf("%d ",16/cube(2)); // Prints 2.
1実際には、テキストはプリプロセッサ トークンに解析され、その他の構文上の問題が発生する可能性があります。マクロ置換の大部分はテキスト置換ですが、いくつかの複雑な問題が発生する可能性があります。
gcc を使用している場合は、-E を指定してコンパイルし、プリプロセッサの出力を確認します
gcc -E demo.c > out.c
これで次回も助かります
立方体はマクロなので、
16/cube(2)
プリプロセッサを介して評価されます
16/2*2*2
32になります。
(関数ではなく) マクロが必要な場合は、入力と出力を角かっこで囲みます。例えば
#define cube(x) ((x)*(x)*(x))
しかし、私は本当にここで関数を使用したいと思います.
マクロを使用する場合は、細心の注意を払う必要があります。関数のように見えますが、実際には関数ではありません。コンパイル時にプリプロセッサはマクロを見つけた場所に展開するだけなので、マクロの最初の使用時に
printf("%d ",cube(2)); expands into printf("%d",x*x*x); then it prints 8
printf("%d ",16+cube(2)); expands into printf("%d",16+x*x*x); then it prints 24
printf("%d ",16/cube(2)); expands into printf("%d",16/x*x*x); but prints 32