重複の可能性:
#defineを使用して定義されている数値の2乗
次のコードが「29」を出力する理由を説明してください。
#define Square(x) (x*(x))
void main()
{
int x = 5;
printf("%d", Square(x+3));
}
重複の可能性:
#defineを使用して定義されている数値の2乗
次のコードが「29」を出力する理由を説明してください。
#define Square(x) (x*(x))
void main()
{
int x = 5;
printf("%d", Square(x+3));
}
マクロはテキストの置換のみを行うため、最終的には次のようになります。
x + 3 * (x + 3)
これは29です。
絶対に常に括弧の間にマクロ引数を置く必要があります。
#define Square(x) ((x)*(x))
さらに良いことに、関数を使用し、コンパイラーを信頼してインライン化します。
編集
leemesが指摘しているように、マクロがx
2回評価されるという事実は問題になる可能性があります。関数またはgccステートメント式などのより複雑なメカニズムを使用すると、これを解決できます。これが不器用な試みです:
#define Square(x) ({ \
typeof(x) y = (x); \
y*y; \
})
マクロですがご注意ください
#define Square(x) ((x)*(x))
問題を解決しているようですが、そうではありません。このことを考慮:
int x = 5;
printf("%d\n", Square(x++));
プリプロセッサはこれを次のように拡張します。
((x++)*(x++))
これは未定義の動作です。一部のコンパイラはこれを次のように評価します
(5 * 5)
そもそも予想通りのようです。しかしx = 7
その後、インクリメント演算子が2回適用されたため。明らかにあなたが探していたものではありません。
出力については、ここを参照してください:http: //ideone.com/9xwyaP
(*インライン関数の代わりに使用される傾向のあるマクロ。)
これは、すべての型を処理できるテンプレート関数を使用してC ++で修正でき、具体的な型を指定することでCで修正できます(Cではオーバーロードもサポートされていないため、取得できる最善の方法は接尾辞付きのさまざまな関数です)。
// C
int SquareI(int x) { return x * x; }
float SquareF(float x) { return x * x; }
double SquareD(double x) { return x * x; }
// C++
template<typename T>
T Square(T x) { return x * x; }
特にGCCの場合、別の解決策があります。GCCはtypeof
演算子を提供するため、マクロ内に一時的な値を導入できます。
#define Square(x) ({ typeof (x) _x = (x); _x * _x; })
その他:http ://ideone.com/OGu08W
演算子の優先順位。ご覧のとおり、Squareは関数ではなくマクロであるため、コンパイラが実際に認識するのは次のとおりです。
(x+3*(x+3))
どの演算子の優先順位が最終的に次のようになりますか。
5 + (3 * (8))
または29.問題を解決するには:
#define Square(x) ((x)*(x))
プリプロセッサはSquare(x)をx *(x)に置き換えました。
コードはのようになりprintf("%d", x+3*(x))
ます。
を使用する必要があります#define Square(x) ((x)*(x))
。
#define square(X) (x*(x))
はマクロであるため、コンパイラはマクロを次のコードに置き換えます。
square(x+3) = x+3*(x+3)
= 5+3*(5+3) = 5+3*(8) = 29