对于定义为 0 的宏,#ifdef 和 #if 之间的细微差别

问题描述 投票:0回答:3

给出下面的 C 文件:

文件macros.c

#ifdef MACRO
#  error MACRO is defined
#else
#  error MACRO is undefined
#endif
#if MACRO
#  error MACRO is non-zero
#else
#  error MACRO is zero
#endif

以下的预期输出是什么?

gcc           -c macros.c
gcc -DMACRO   -c macros.c
gcc -DMACRO=0 -c macros.c

答案:这是我机器上的 gcc 预处理器的作用。

gcc           -c macros.c

输出:

macros.c:4:4: error: #error MACRO is undefined
macros.c:9:4: error: #error MACRO is zero

并且:

gcc -DMACRO   -c macros.c

输出:

macros.c:2:4: error: #error MACRO is defined
macros.c:7:4: error: #error MACRO is non-zero

并且:

gcc -DMACRO=0 -c macros.c

输出:

macros.c:2:4: error: #error MACRO is defined
macros.c:9:4: error: #error MACRO is zero

课程

#ifdef MACRO
对于定义性计算结果为 true 即使定义值为 0(零)

这是另一个 C 预处理器陷阱!按照 C 标准,这应该是这样吗?

c macros c-preprocessor
3个回答
9
投票

为了评估

#if
语句的控制表达式,任何未定义的宏都将被视为定义为 0。来自 C99 §6.10.1/3-4(添加强调):

3)表单的预处理指令

# if constant-expression new-line group
opt

# elif constant-expression new-line group
opt

检查控制常量表达式的计算结果是否为非零。

4) 在评估之前,预处理标记列表中的宏调用将成为 控制常量表达式被替换(修改的宏名称除外) 由

defined
一元运算符),就像在普通文本中一样。如果令牌
defined
是 由于此替换过程或使用
defined
一元运算符而生成 与宏替换之前的两个指定形式之一不匹配,行为是 不明确的。 由于宏展开和
defined
一元进行所有替换之后 运算符已执行,所有剩余的标识符(包括词法上的标识符) 与关键字相同)替换为 pp-number 0
,然后每次预处理 令牌被转换为令牌。 [...]

因此,例如,这样的表达式:

#if !FOO

如果

1
未定义,则计算为
FOO
,因为它将被视为 0,然后
!FOO
将计算为
!0
,即
1


7
投票

 #ifdef 
只关心MACRO是否已定义。价值并不重要。

 #if 
检查 MACRO 的值并相应地评估 MACRO。

这是正确的行为


2
投票

行为符合标准。

C99标准:6.10.1 有条件包含:

第 2 段:表单的预处理指令

# if constant-expression new-line groupopt
# elif constant-expression new-line groupopt

检查控制常量表达式的计算结果是否为非零。

第 4 段:表单的预处理指令

# ifdef identifier new-line groupopt
# ifndef identifier new-line groupopt

检查标识符当前是否定义为宏名称。他们的 条件相当于

#if defined
identifier
#if !defined
identifier 分别。

© www.soinside.com 2019 - 2024. All rights reserved.