什么是具有副作用的表达式,为什么不应该将它们传递给宏? [英] What are expressions with side effects and why should they be not passed to a macro?
问题描述
我在 C How to Program 一文中看到了一个语句:
I came across a statement in the text C How to Program:
具有副作用的表达式(即,变量值被修改)不应传递给宏,因为宏参数可能会被多次计算.".
"Expressions with side effects (i.e., variable values are modified) should not be passed to a macro because macro arguments may be evaluated more than once.".
我的问题是什么是具有副作用的表达式,为什么不应该将它们传递给宏?
My question is what are expressions with side effects and why should they be not passed to a macro?
推荐答案
经典例子是计算两个值的最大值的宏:
The classic example is a macro to calculate the maximum of two value:
#define MAX(a, b) ((a) > (b) ? (a) : (b))
现在让我们像这样调用"宏:
Now lets "call" the macro like this:
int x = 5;
int y = 7;
int z = MAX(x++, y++);
现在如果 MAX
是一个普通函数,我们希望 x
和 y
会增加一次,对吗?然而,因为它是一个宏,所以调用"被替换如下:
Now if MAX
was a normal function, we would expect that x
and y
would be incremented once, right? However because it's a macro the "call" is replaced like this:
int z = ((x++) > (y++) ? (x++) : (y++));
如您所见,变量 y
将增加 两次,一次在条件中,一次作为 三元运算符.
As you see, the variable y
will be incremented twice, once in the condition and once as the end-result of the ternary operator.
这是带有副作用的表达式(后增量表达式)和宏扩展的结果.
This is the result of an expression with side-effects (the post-increment expression) and a macro expansion.
在相关说明中,宏还存在其他危险.例如,让我们使用这个简单的宏:
On a related note, there are also other dangers with macros. For example lets take this simple macro:
#define MUL_BY_TWO(x) (x * 2)
看起来很简单吧?但是现在如果我们像这样使用它会怎样:
Looks simple right? But now what if we use it like this:
int result = MUL_BY_TWO(a + b);
这会像这样扩展
int result = (a + b * 2);
正如您希望知道的那样,乘法的优先级高于加法,因此表达式 a + b * 2
等价于 a + (b * 2)
,可能不是宏作者的意图.这就是为什么宏的参数应该放在它们自己的括号内:
And as you hopefully knows multiplication have higher precedence than addition, so the expression a + b * 2
is equivalent to a + (b * 2)
, probably not what was intended by the macro writer. That is why arguments to macros should be put inside their own parentheses:
#define MUL_BY_TWO(x) ((x) * 2)
那么展开就是
int result = ((a + b) * 2);
这可能是正确的.
这篇关于什么是具有副作用的表达式,为什么不应该将它们传递给宏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!