According to the C++ FAQ, macros are evil:



有人可以解释为什么unsafe(x++)两次增加x吗?我不知道。

最佳答案

通过预处理器运行它会显示问题。使用gcc -E(也可以使用cpp -P,其中-P选项还禁止生成的#行),

inline
int safe(int i)
{
  return i >= 0 ? i : -i;
}

int f();

void userCode(int x)
{
  int ans;

  //    increment 1      increment 2 (one of these)
  //        |             |     |
  //        V             V     V
  ans = ( (x++) >= 0 ? (x++) : -(x++) );
  ans = ( (f()) >= 0 ? (f()) : -(f()) );

  ans = safe(x++);
  ans = safe(f());
}

如无杂音说明,f()宏还两次调用了unsafe函数。也许它是纯净的(没有副作用),所以它本身并没有错。但是仍然不是最理想的。

因此,由于内联函数通常比类似函数的宏更安全,因为它们与其他基本元素(变量和表达式;对于 list 常量,enum通常可以更整洁; 宏有什么好的用途?

设置仅在编译时已知的常量。 编译时,可以从命令行定义宏。代替
#define X 12

在源文件中,您可以添加
-DX=12

cc命令。您也可以使用#undef X从命令行-UX

例如,这允许诸如条件编译之类的事情。
#if X
   do this;
#else
   do that;
#endif
   while (loop);

由makefile控制,makefile本身可能是通过配置脚本生成的。

X宏。 X-Macros(IMO)最引人注目的用途是将enum标识符与可打印的字符串相关联。虽然一开始看起来很有趣,但它减少了此类并行定义的重复和同步问题。
#define NAMES(_) _(Alice) _(Bob) _(Caravaggio) _(DuncanIdaho)
#define BARE(_) _ ,
#define STRG(_) #_ ,
enum { NAMES(BARE) };
char *names[] = { NAMES(STRG) };

请注意,您可以将宏的名称作为参数传递给另一个宏,然后使用该参数就好像它本身是一个宏一样来调用传递的宏(因为它是一个宏)。有关X-Macros的更多信息,请参见this question

10-07 15:46