宏名称和替换列表相同

时间:2012-09-04 11:41:05

标签: c++ macros replace

我找到了一些宏名称和替换列表相同的预处理指令。例如,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标准中的相关规定是什么?

4 个答案:

答案 0 :(得分:5)

C ++ 11标准第16.3.4节第2段:

阻止了宏替换期间的无限递归
  

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

基本上,这意味着在自己的扩展中出现的宏不会再被替换。

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

答案 1 :(得分:2)

除了其他答案之外,定义这些宏将有助于编译器生成“宏重新定义”错误消息,如果任何人,任何地方都有重新定义bool的真实想法,无论是真还是假。

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

答案 2 :(得分:1)

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

示例(C11,7.2 / 2):

  

assert宏应实现为宏,而不是实际功能。如果   为了访问实际函数,宏定义被抑制,行为是   未定义。

您的实施完全有合理的assert功能。

为了好玩,以下是一些“未指定”的东西,它们是宏还是带有外部链接的标识符:

  • errno

  • setjmp

  • va_copyva_end

  • putcgetc

答案 3 :(得分:1)

宏扩展不会递归,因此它们将终止。

拥有宏的一个优点是您可以在预处理器中对其进行测试

#if defined bool
...
#endif

仅在bool为宏时才有效。