2012-09-04 68 views
3

我发现了一些宏名称和替换列表相同的预处理指令。例如,gcc提供的stdbool.h中的一些预处理指令。宏名称和替换列表相同

#else /* __cplusplus */ 

/* Supporting <stdbool.h> in C++ is a GCC extension. */ 
#define _Bool bool 
#define bool bool 
#define false false 
#define true true 

#endif /* __cplusplus */ 

我不明白为什么程序员编写了这些预处理指令。它们是无用的,替换会浪费时间。我知道这不会导致无限递归。如何避免无限递归? C标准中的相关规定是什么?

+0

因为定义关键字是一个错误,所以在您自己的代码中编写这将不合法。由于这是实施的一部分,我想这是不同的。 – jcoder

回答

5

无限递归由C++ 11标准部防止16.3.4第2段:

如果该扫描替换列表的过程中发现被替换的宏的名称(不包括源文件的预处理令牌的其余部分),它不会被替换。此外,如果任何嵌套替换 遇到被替换的宏的名称,它不会被替换。这些未替换的宏名预处理令牌不再可用于进一步的替换,即使它们在上下文 (其中该宏名预处理令牌将否被替换)中稍后(重新)检查。

基本上,这意味着一个出现在其自身扩展内部的宏将不会被再次替换。

true,boolfalse被GCC扩展定义为宏的原因是为了使C++代码与C99更加兼​​容。在C99中,这些被定义为stdbool.h中的宏,因此代码可以检查它们是否使用例如。 #ifdef bool

1

有时候标准说“X必须是宏”。如果您的语言已具有固有的X,则必须说#define X X符合标准。 (例如,用户可以说#ifdef X和期望这是真实的。)

实施例(C11,7.2/2):

assert宏应被实现为一个宏,而不是实际的功能。如果为了访问实际功能而禁止宏定义 ,则行为为 未定义。

您的实施完全可能具有实际的assert功能。

为了好玩,这里有一些东西是 “未指定”,即:是否是宏或标识符有外部链接:

  • errno

  • setjmp

  • va_copyva_end

  • putcgetc

1

宏展开不循环,所以他们将终止。有一个宏观的

一个好处是,你可以在预处理

#if defined bool 
... 
#endif 

只有bool是一个宏观的工作进行测试。

宏替换期间
+0

为什么你需要测试这个? –

+0

如果你包含''并且认为代码在C. –

+0

那么你可能想要。但适当的测试是针对'__bool_true_false_are_defined'。 –

2

除了其他答案,定义这些宏将帮助编译器生成“宏重新定义”错误消息,如果任何人在任何地方都有重新定义bool,true或false的绝妙想法。

请参阅标准第16.3节 - 在宏重新定义中只允许使用相同的替换列表。

相关问题