5

重複の可能性:
#defineを使用して定義されている数値の2乗

次のコードが「29」を出力する理由を説明してください。

#define Square(x) (x*(x))

void main()
{
    int x = 5;
    printf("%d", Square(x+3));
}
4

5 に答える 5

24

マクロはテキストの置換のみを行うため、最終的には次のようになります。

x + 3 * (x + 3)

これは29です。

絶対に常に括弧の間にマクロ引数を置く必要があります。

#define Square(x) ((x)*(x))

さらに良いことに、関数を使用し、コンパイラーを信頼してインライン化します。


編集

leemesが指摘しているように、マクロがx2回評価されるという事実は問題になる可能性があります。関数またはgccステートメント式などのより複雑なメカニズムを使用すると、これを解決できます。これが不器用な試みです:

#define Square(x) ({    \
    typeof(x) y = (x);  \
    y*y;                \
})
于 2013-02-02T14:21:54.803 に答える
8

マクロですがご注意ください

#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

于 2013-02-02T14:32:37.817 に答える
7

演算子の優先順位。ご覧のとおり、Squareは関数ではなくマクロであるため、コンパイラが実際に認識するのは次のとおりです。

(x+3*(x+3))

どの演算子の優先順位が最終的に次のようになりますか。

5 + (3 * (8))

または29.問題を解決するには:

#define Square(x) ((x)*(x))
于 2013-02-02T14:23:38.427 に答える
4

プリプロセッサはSquare(x)をx *(x)に置き換えました。

コードはのようになりprintf("%d", x+3*(x))ます。

を使用する必要があります#define Square(x) ((x)*(x))

于 2013-02-02T14:23:03.970 に答える
1

#define square(X) (x*(x))はマクロであるため、コンパイラはマクロを次のコードに置き換えます。

square(x+3) = x+3*(x+3)

     = 5+3*(5+3) = 5+3*(8) = 29
于 2013-02-02T14:28:10.113 に答える