C ++ FAQ的不安全宏解释? [英] Explanation of C++ FAQ's unsafe macro?
问题描述
[9.5]为什么我应该用内联函数而不是简单的#define
宏?
[9.5] Why should I use inline functions instead of plain old #define macros?
由于的#define
宏在4个不同的罪恶:罪恶#1,罪恶#2,
邪恶的#3,#邪4。有时候,你无论如何都应该使用他们,但他们
还是邪恶的。
不像的#define
宏,内联函数避免臭名昭著的宏观错误,因为内联函数总是精确地评估每个参数
一旦。换句话说,调用内联函数在语义上只
就像调用一个普通的功能,只是速度更快:
Because #define
macros are evil in 4 different ways: evil#1, evil#2,
evil#3, and evil#4. Sometimes you should use them anyway, but they're
still evil.
Unlike #define
macros, inline functions avoid infamous macro errors since inline functions always evaluate every argument exactly
once. In other words, invoking an inline function is semantically just
like invoking a regular function, only faster:
// 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
}
也不像宏,参数类型进行检查,并在必要
转换正确执行。
Also unlike macros, argument types are checked, and necessary conversions are performed correctly.
宏是对健康不利;除非你有没有使用这些。
Macros are bad for your health; don't use them unless you have to.
有人能解释为什么是不安全(X ++)
递增 X
两次?我无法弄清楚。
Can someone explain why is unsafe(x++)
increments x
twice? I am not able to figure out.
推荐答案
通过preprocessor运行它说明问题了。使用的gcc -E
(也可以使用 CPP-P
,其中 -P 产生code>选项还燮presses
#
行),
Running it through the preprocessor shows the problem. Using gcc -E
(can also use cpp -P
, where the -P
option also suppresses generated #
lines),
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()
也由不安全
宏调用两次。也许它的纯粹的(没有副作用),所以它不是的错误的,本身。但还是不理想。
As artless noise notes, the function f()
is also called twice by the unsafe
macro. Perhaps it's pure (has no side-effects) so it's not wrong, per se. But still suboptimal.
所以,因为内联函数比函数宏通常更安全,因为他们在与其他基本要素相同的语义层面的工作:变量和前pressions;和清单常量,枚举
s时,可以常常更加的整理的; 什么是的好的宏的使用?
So, since inline functions are generally safer than function-like macros because they work on the same semantic level with the other basic elements: variables and expressions; and for manifest constants, enum
s can often be more tidy; what are the good uses of macros?
设置只在编译时已知常量。您可以在编译时定义的命令行的宏。而不是
Setting constants known only at compile-time. You can define a macro from the command-line when compiling. Instead of
#define X 12
在源文件中,可以添加
in the source file, you can add
-DX=12
到 CC
命令。您也可以和#undef X
从与命令行-UX
。
to the cc
command. You can also #undef X
from the command-line with -UX
.
这样可以允许有条件的编译,如:
This allows things like conditional-compilation, eg.
#if X
do this;
#else
do that;
#endif
while (loop);
由一个makefile控制,本身或许与配置脚本生成的。
to be controlled by a makefile, itself perhaps generated with a configure script.
X-宏即可。用于X宏最引人注目的使用,国际海事组织,是有关联的字符串打印枚举
标识符。虽然它让看第一好笑,这降低了这些类型的并行定义重复和同步问题。
X-Macros. The most compelling use for X-Macros, IMO, is associating enum
identifiers with printable strings. While it make look funny at first, it reduces duplication and synchronization issues with these kinds of parallel definitions.
#define NAMES(_) _(Alice) _(Bob) _(Caravaggio) _(DuncanIdaho)
#define BARE(_) _ ,
#define STRG(_) #_ ,
enum { NAMES(BARE) };
char *names[] = { NAMES(STRG) };
注意,您可以通过使用参数传递宏的名称作为参数传递给另一个宏,然后调用通过宏观的,如果的它是自己的宏(因为它的是之一)。欲了解更多有关的X宏,请参见这个问题。
Notice that you can pass a macro's name as an argument to another macro and then call the passed macro by using the argument as if it were itself a macro (because it is one). For more on X-Macros, see this question.
这篇关于C ++ FAQ的不安全宏解释?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!