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

时间:2014-01-23 15:32:55

标签: c macros c-preprocessor

鉴于以下C文件:

$ cat 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标准,它应该如何?

3 个答案:

答案 0 :(得分:7)

为了评估#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 1}}。

答案 1 :(得分:5)

#ifdef 只关心MACRO是否已被定义。价值无关紧要。

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

这是正确的行为

答案 2 :(得分: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 标识符#if !defined 标识符 分别