对于定义为0的宏,#ifdef和#if之间的细微差别 [英] The subtle difference between #ifdef and #if for a macro defined as 0

查看:429
本文介绍了对于定义为0的宏,#ifdef和#if之间的细微差别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下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

以下内容的预期输出是什么?

What is the expected output of the following?

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

答案:这是我计算机上gcc的预处理器所做的事情.

Answer: Here's what the gcc's preprocessor on my machine does.

$ 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
$

教训:即使定义的值为0(零),#ifdef MACRO对于确定的值为仍为true.

Lesson: #ifdef MACRO evaluates to true for defined-ness even if the defined value is 0 (zero).

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

Another C preprocessor gotcha! Is this how it should be as per the C standard?

推荐答案

任何未定义的宏都将被视为0,以评估#if语句的控制表达式.从C99§6.10.1/3-4(添加重点)开始:

Any undefined macro is treated as it were defined as 0 for the purposes of evaluating the controlling expressions of #if statements. From C99 §6.10.1/3-4 (emphasis added):

3)表单的预处理指令

3) Preprocessing directives of the forms

# if constant-expression new-line group opt
# elif constant-expression new-line group opt

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

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

check whether the controlling constant expression evaluates to nonzero.

4)在评估之前,预处理令牌列表中的宏调用将变为 控制常量表达式被替换(那些宏名被修改后除外) 由defined一元运算符),就像在普通文本中一样.如果令牌defined是 此替换过程或使用defined一元运算符产生的结果 与宏替换之前指定的两种形式之一不匹配,其行为是 不明确的. 在由于宏扩展和defined一元制而进行的所有替换之后 操作符已执行,所有剩余的标识符(包括按词法识别的标识符) 与关键字相同)被替换为pp-number 0 ,然后进行每个预处理 令牌转换为令牌. [...]

4) Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the controlling constant expression are replaced (except for those macro names modified by the defined unary operator), just as in normal text. If the token defined is generated as a result of this replacement process or use of the defined unary operator does not match one of the two specified forms prior to macro replacement, the behavior is undefined. After all replacements due to macro expansion and the defined unary operator have been performed, all remaining identifiers (including those lexically identical to keywords) are replaced with the pp-number 0, and then each preprocessing token is converted into a token. [...]

例如,这样的表达式:

#if !FOO

如果未定义FOO,则将评估为1,因为它将被视为0,然后将!FOO评估为!0,即1.

Will evaluate to 1 if FOO is undefined, since it will be treated as a 0, and then !FOO would be evaluated as !0, which is 1.

这篇关于对于定义为0的宏,#ifdef和#if之间的细微差别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆