有副作用的表达式是什么,为什么不将它们传递给宏? [英] What are expressions with side effects and why should they be not passed to a macro?
问题描述
我在C语言如何编程中遇到一个声明:
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
会被递增一次,对吗?但是,因为它是一个宏,所以"call"被替换为:
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屋!