在学习 C 预处理器
#if
时,我遇到了这个特定的语句,在 GCC 站点上给出的语法中描述了术语表达式,语法:
#if *expression*
controlled text
#endif
在上述语法中描述的表达式的上下文中,以下语句意味着什么?
声明:在C语言中,表达式可以包含非宏的标识符,这些标识符都被视为数字零。如果您知道 MACRO 在定义时将始终具有非零值,则这允许您编写
#if MACRO
而不是 #ifdef MACRO
。在没有函数调用括号的情况下使用的类似函数的宏也被视为零。
在某些情况下,这种捷径是不可取的。这 -Wundef 选项会导致 GCC 在遇到不是
#if
中的宏的标识符时发出警告。
在 C 中,表达式可能包含非宏的标识符,这些标识符都被视为数字零。
这意味着,如果您有
#if
指令,例如:
#if X == 3
且
X
未定义为预处理器宏,则将其替换为 0
,因此该指令将被处理为:
#if 0 == 3
这是标准的 C 行为。 GCC 的
-Wundef
选项要求编译器在发生这种情况时发出警告。
有一个例外;标识符
defined
经过特殊处理。如果 defined identifier
或 defined (identifier)
出现在 #if
指令中,则根据 identifier
是否是定义的宏,将其替换为 1 或 0。
这允许您写
而不是#if MACRO
,如果您知道 MACRO 在定义时将始终具有非零值。#ifdef MACRO
由于上述替换,如果
#if MACRO
是已定义的类对象宏,则 #if replacement
将变为 MACRO
,否则将变为 #if 0
。那么我们有以下几种情况:
MACRO
是一个类似对象的宏,可扩展为非零值:#if MACRO
将其评估为 true,而 #ifdef MACRO
将其条件评估为 true。MACRO
是一个类似对象的宏,可扩展为零:#if MACRO
将其评估为 false,而 #ifdef MACRO
将其条件评估为 true。MACRO
未定义为类似对象的宏:#if MACRO
变为 #if 0
并被评估为 false,并且 #ifdef MACRO
评估其条件为 false。因此,如果
#if MACRO
不是值为零的表达式,则 #ifdef MACRO
和 MACRO
的行为相同。
注意:类似对象的宏没有参数,如下所示:
#define MACRO (3+4)
并且类似函数的宏具有参数,如下所示:
#define MACRO(x) (3+(x))
在没有函数调用括号的情况下使用的类似函数的宏也被视为零。
如果
MACRO
被定义为类似函数的宏,则在 #if MACRO
中,不执行宏替换。这是因为类函数宏只有在后面跟有括号时才会被替换,如 #if MACRO(3)
中所示。因此,在宏替换被拒绝后,它继续用 0
替换标识符,变成 #if 0
。