类似宏的函数和奇怪的行为

Function-like macros and strange behavior

本文关键字:函数      更新时间:2023-10-16

我已经开始阅读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中使用一个简单的print语句,7会在第一次调用中被打印出来,但我一辈子都不知道为什么。我是不是错过了一些显而易见的东西?

编译器会逐字逐句地用您传入的内容替换宏。所以你最终得到

int a = 5, b = 0;
f((++a) > (b) ? (++a) : (b));
f((++a) > (b+10) ? (++a) : (b+10));

使用g++ -E myprog.cpp(如果不使用g++,请将g++替换为whatever-your-compiler-is)-它适用于几乎所有编译器,它将在预处理后生成实际的内容。

这是一个很好的例子,说明了为什么不应该使用宏来做函数类型的事情。

如果你使用内联函数,你会得到更多你(可能)期望的东西:

 inline void CallWithMax(int a, int b) 
 {
     f((a) > (b) ? (a) : (b));
 }

任何一个优秀的编译器都应该能够做到这一点,至少和宏一样高效,还有一个额外的优势,即在调用代码中对ab求值一次,不会发生任何"奇怪"的事情。

如果使用调试符号构建代码,您也可以逐步执行内联函数,因此,如果您想查看函数中ab的实际值,可以这样做。宏,因为它们扩展到源代码中的原始位置,所以你无法真正看到里面发生了什么。