Herbert Schildt说:
在某些情况下,应该使用真实函数来代替类似函数的宏,例如:其中代码大小要最小化,或者参数不能多次评估。
"他的意思是什么?不能多次评估一个参数?"
答案 0 :(得分:50)
让我们用宏来计算两个值的最大值:
#define MAX(a, b) ((a) < (b) ? (a) : (b))
然后我们像这样使用它:
int x = 5;
int y = 10;
int max = MAX(x++, y++);
然后将宏扩展为
int max = ((x++) < (y++) ? (x++) : (y++));
正如您所看到的,x
或y
上的增量操作将发生两次,而不是如果你有一个函数,你传递的每个参数是只评估一次。
另一个重点是在宏中使用括号。我们来看另一个简单的宏:
#define MUL(a, b) a * b
现在,如果您将宏调用为
int sum = MUL(x + 3, y - 2);
然后扩展变为
int sum = x + 3 * y - 2;
归因于operator precedence等于
int sum = x + (3 * y) - 2;
如果期望(x + 3) * (y - 2)
,通常不会达到预期效果。
使用函数也可以“解决”这个问题。
答案 1 :(得分:4)
有时论据有副作用。
例如,i++
的值为i
,但i
的值增加1.因此,下一个i++
的值将为{{1 }}。
在宏中,每次调用时都会对参数进行求值,从而产生结果值;在函数中,(实际)参数被计算并复制到函数内的(正式)参数中,从而消除了副作用。
在使用功能时,您不关心副作用。但是,隐式类型提升和转换可能容易出错。