我已经开始阅读Effective C ++了,在第2项的某些时候,提到了以下内容:
// call f with the maximum of a and b
#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))
...
int a = 5, b = 0;
CALL_WITH_MAX(++a, b); // a is incremented twice
CALL_WITH_MAX(++a, b+10); // a is incremented once
这里是a在调用f之前递增的次数 取决于与之相比的内容!
实际上,如果我在f
中使用简单的打印语句,则在第一次调用时会打印7,但我不能为我的生活找出原因。我错过了一些明显的东西吗
答案 0 :(得分:5)
编译器将文本替换为您传入的内容,逐字逐句。所以你最终得到了
int a = 5, b = 0;
f((++a) > (b) ? (++a) : (b));
f((++a) > (b+10) ? (++a) : (b+10));
答案 1 :(得分:1)
使用g++ -E myprog.cpp
(如果您不使用g++
,请将whatever-your-compiler-is
替换为g++
) - 它可以在ALMOST所有编译器上运行,它会在预处理后产生实际内容。
这是一个很好的例子,说明为什么你不应该使用宏来做函数类型的东西。
如果您使用内联函数,您可以获得更多(可能)期望的内容:
inline void CallWithMax(int a, int b)
{
f((a) > (b) ? (a) : (b));
}
任何体面的编译器都应该能够像宏一样高效地执行此操作,并且在调用代码中对a
和b
进行一次评估,并且没有任何“怪异”的额外优势发生。
如果使用调试符号构建代码,也可以逐步执行内联函数,因此,如果要查看函数内部实际存在的值a
和b
,则可以执行此操作。宏,因为它们扩展到源代码中的原始位置,所以你无法真正看到内部发生的事情。