0

このマクロを定義すると、次のようになります。

#define SQR(x) x*x

この表現を言いましょう:

SQR(a+b)

この式はマクロに置き換えられ、次のようになります。

a+b*a+b

++しかし、式の前に演算子を置くと、次のようになります。

++SQR(a+b)

今の表情はどうですか?これ++はSQRパラメットのすべての部分の前に配置されていますか?このような:

++a+b*++a+b

ここで私は簡単なプログラムを与えます:

#define SQR(x) x*x
int a, k = 3;
a = SQR(k+1) // 7
a = ++SQR(k+1) //9
4

5 に答える 5

5

マクロを定義するときは、基本的に、最初の例のような奇妙な動作を防ぐために、マクロ パラメーターを括弧に入れて、結果を括弧に入れて、副作用なしで安全に使用できるようにする必要があります使用する

#define SQR(x) ((x)*(x))

は、数学的に正しいものにSQR(a+b)展開されます ( ab+a+b に等しい とは異なります)。((a+b)*(a+b))a+b*a+b

マクロの前後に何かを置いても、マクロには入りません。あなたの例ではそう++SQR(x)なり++x*xます。

次の点に注意してください。

int a=3, b=1;
SQR(a+b) // ==> a+b*a+b = 3+1*3+1 = 7
++SQR(a+b) // ==> ++a+b*a+b ==> 4 + 1*4 + 1 = 9
           // since preincrement will affect the value of a before it is read.

いずれかの時間、つまりインクリメントを読み取る++SQR(a+b)前にプリインクリメントが開始され、その後 2 回使用されるため、結果が予想より 2 高くなるため、 2 ずつインクリメントしているように見えます。aa

@JonathanLeffler が指摘するように、後者の呼び出しは未定義の動作を呼び出します。評価が左から右に行われるとは限りません。異なるコンパイラ/OS では異なる結果が生成される可能性があるため、決して依存しないでください。

于 2012-09-20T04:31:30.690 に答える
1

C++ の場合、このマクロを定義する正しい方法は、マクロを使用せず、代わりに次を使用することです。

template<typename T> static T SQR( T a ) { return a*a; }

これにより、マクロが間違っているいくつかの恐ろしいケースが正しくなります。

例えば:

SQR(++a); 

関数形式++aを使用すると、一度評価されます。マクロ形式では、シーケンス ポイント間で値を複数回変更して読み取ると、未定義の動作が発生します (少なくとも C++ の場合)。

于 2012-09-20T04:47:12.807 に答える
0

マクロ定義は単にコードを置き換えるだけなので、通常は括弧で囲むのが望ましいです。そうしないと、コードが望ましくない方法で置き換えられる可能性があります。

したがって、次のように定義すると:

#define SQR(x) ((x)*(x))

それから

++SQR(a+b) = ++((a+b)*(a+b))

于 2012-09-20T04:36:30.543 に答える
0

あなたの例では、++SQR(a+b)として展開する必要があります++a+b*a+b
したがって、a == 3 および b == 1 の9場合、コンパイラが左から右に評価すると、答えが得られます。

しかし、どこが無効で++SQR(3+1)あるかとして展開されるため、ステートメントは正しくありません。++3+1*3+1++3

于 2012-09-20T04:42:12.540 に答える
0

プリプロセッサでは、++a+b*a+b と評価されます。正しい方法は、次のように、各用語と全体を括弧で囲みます。

#define SQR(x)  ((x)*(x))
于 2012-09-20T04:45:24.717 に答える