Gau*_*v K 31 c c++ c-preprocessor
[9.5]为什么我应该使用内联函数而不是普通的旧#define宏?
因为
#define宏在四种不同的方面是邪恶的:邪恶的#1,邪恶的#2,邪恶的#3和邪恶的#4.有时你应该使用它们,但它们仍然是邪恶的.与#define宏不同,内联函数避免了臭名昭着的宏错误,因为内联函数总是只评估每个参数一次.换句话说,调用内联函数在语义上就像调用常规函数一样,只是更快:Run Code Online (Sandbox Code Playgroud)// A macro that returns the absolute value of i #define unsafe(i) \ ( (i) >= 0 ? (i) : -(i) ) // An inline function that returns the absolute value of i inline int safe(int i) { return i >= 0 ? i : -i; } int f(); void userCode(int x) { int ans; ans = unsafe(x++); // Error! x is incremented twice ans = unsafe(f()); // Danger! f() is called twice ans = safe(x++); // Correct! x is incremented once ans = safe(f()); // Correct! f() is called once }与宏不同,还会检查参数类型,并正确执行必要的转换.
宏对你的健康有害; 除非必须,否则不要使用它们.
有人可以解释为什么unsafe(x++)增量x两次?我无法搞清楚.
lus*_*oog 69
通过预处理器运行它会显示问题.使用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());
}
Run Code Online (Sandbox Code Playgroud)
作为无艺术的噪音音符,该功能f()也被unsafe宏调用两次.也许它是纯粹的(没有副作用)所以它本身并没有错.但仍然不是最理想的.
因此,因为内联函数通常比类似函数的宏更安全,因为它们与其他基本元素在同一语义级别上工作:变量和表达式; 对于显式常数,enums通常可以更整洁 ; 宏的好用是什么?
设置常量仅在编译时知道.您可以在编译时从命令行定义宏.代替
#define X 12
Run Code Online (Sandbox Code Playgroud)
在源文件中,您可以添加
-DX=12
Run Code Online (Sandbox Code Playgroud)
对cc命令.您也可以#undef X从命令行中使用-UX.
这允许条件编译之类的东西,例如.
#if X
do this;
#else
do that;
#endif
while (loop);
Run Code Online (Sandbox Code Playgroud)
由makefile控制,它本身可能是用configure脚本生成的.
X-Macros.对于X-Macros,IMO最引人注目的用途是将enum标识符与可打印字符串相关联.虽然它起初看起来很有趣,但它减少了这些并行定义的重复和同步问题.
#define NAMES(_) _(Alice) _(Bob) _(Caravaggio) _(DuncanIdaho)
#define BARE(_) _ ,
#define STRG(_) #_ ,
enum { NAMES(BARE) };
char *names[] = { NAMES(STRG) };
Run Code Online (Sandbox Code Playgroud)
请注意,您可以将宏的名称作为参数传递给另一个宏,然后使用该参数调用传递的宏,就好像它本身就是一个宏(因为它是一个宏).有关X-Macros的更多信息,请参阅此问题.
Dre*_*ann 17
宏在编译程序之前有效地进行复制/粘贴.
unsafe(x++)
Run Code Online (Sandbox Code Playgroud)
会成为
( (x++) >= 0 ? (x++) : -(x++) )
Run Code Online (Sandbox Code Playgroud)
And*_*mas 10
预编译器在编译之前替换宏.
编译器看到了这个:
( (x++) >= 0 ? (x++) : -(x++) )
Run Code Online (Sandbox Code Playgroud)