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。