如何正确扩展此宏?

hak*_*ami 0 c c++ macros

当我定义这个宏时:

#define SQR(x) x*x
Run Code Online (Sandbox Code Playgroud)

让我们说这个表达式:

SQR(a+b)
Run Code Online (Sandbox Code Playgroud)

此表达式将被宏替换,如下所示:

a+b*a+b
Run Code Online (Sandbox Code Playgroud)

但是,如果我++在表达式之前放置一个运算符:

++SQR(a+b)
Run Code Online (Sandbox Code Playgroud)

现在的表达是什么样的?这是++放置在SQR参数的每个部分吗?像这样:

++a+b*++a+b
Run Code Online (Sandbox Code Playgroud)

在这里我给出一个简单的程序:

#define SQR(x) x*x
int a, k = 3;
a = SQR(k+1) // 7
a = ++SQR(k+1) //9
Run Code Online (Sandbox Code Playgroud)

nne*_*neo 5

在定义宏时,您基本上总是希望将宏参数放在parens中以防止第一个示例中的那种奇怪的行为,并将结果放在parens中,以便可以安全地使用它而不会产生副作用.运用

#define SQR(x) ((x)*(x))
Run Code Online (Sandbox Code Playgroud)

使SQR(a+b)扩展到((a+b)*(a+b))数学上是正确的(不像a+b*a+b,等于ab + 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.
Run Code Online (Sandbox Code Playgroud)

你看到++SQR(a+b)似乎增加了2,因为在a我读取任何一个时间之前,前增量开始,即a增量,然后使用两次,因此结果比预期高2.

注意 @JonathanLeffler指出,后一个调用调用未定义的行为; 评估不保证从左到右进行.它可能会在不同的编译器/操作系统上产生不同的结果,因此永远不应该依赖它们.

  • @stevenyang:编译器喜欢的任何方式; 它可以给你任何答案(-1,37,496),它仍然是一个有效的答案,因为你已经调用了未定义的行为. (3认同)
  • 温和的挑战问题:你能想到在这样的例子中需要在宏参数名称周围添加括号的情况:`#define macro(a,b)some_func(1,a,b,__ FILE __,_ _ _ _ _ _ _ `?_Hint:_我不能,但我是凡人. (2认同)
  • @stevenyang不,优先权没有说明首先评估什么,只说明隐含括号的方式. (2认同)