c - #if 指令中的评估顺序:宏扩展与“定义”关键字
问题描述
当 c 预处理器运行#if
/#elif
预处理指令时,它对直接跟随的标记执行 4 次操作:
defined {identifier}
用1
if{identifier}
定义替换每一个出现,0
否则。- 调用所有宏。
- 用 替换所有剩余的标识符
0
。 - 将结果解析并评估为
constant-expression
.
现在,从标准 (c99, 6.10.1) 中可以清楚地看出,步骤 3 和 4 实际上是按此顺序发生的,并且在完成 1 和 2 之后。但我找不到关于 1 和 2 顺序的任何说明。
从我所做的一些有限测试来看,gcc 似乎根据令牌的顺序执行步骤 1 和 2 - in defined MACRO
,defined
首先执行,但在MACRO(defined ID)
宏中执行。
这种行为是标准要求的吗?实现定义?不明确的?
解决方案
首先执行您的第 2 步。顺序为步骤 2、1、3、4:
C 2018 6.10.1 4 说[强调我的]:
在评估之前,预处理标记列表中将成为控制常量表达式的宏调用被替换(除了那些被
defined
一元运算符修改的宏名称),就像在普通文本中一样......</p>
6.10.1 1 表示#if
or的控制表达式#elif
应该是一个整数常量表达式,它可以另外包含表达式or :defined identifier
defined ( identifier )
...如果标识符当前被定义为宏名称(即,如果它是预定义的,或者如果它是预处理指令的主题,而没有具有相同主题标识符的中间指令),则评估为 1,否则为0。
#define
#undef
因此,按照 6.10.1 4 执行第一次宏替换,然后执行表达式的评估。
请注意,尽管宏替换首先发生,但如果它生成defined
令牌,它们不一定会被评估,因为 6.10.1 4 继续说:
…如果令牌
defined
是作为这个替换过程的结果生成的…,行为是未定义的。
然后按照 6.10.1 4 再次执行您的第 3 步:
... 在所有因宏扩展和
defined
一元运算符而导致的替换完成后,所有剩余的标识符(包括那些在词法上与关键字相同的标识符)都被替换为 pp-number0
,然后将每个预处理标记转换为一个标记…</p>
然后评估控制表达式,您的步骤 4:
... 生成的标记组成控制常量表达式,根据 6.6 的规则进行评估...</p>
推荐阅读
- fullpage.js - 防止向下滑动以对 Fullpage js 中的鼠标滚轮滚动执行一些其他操作
- ios - 如何在第一个和最后一个colllectionview单元格中提供前导和尾随空间
- javascript -
不支持在使用 componentWillMount 或 componentWillUnMount 时动态更改 `store` - c# - 使用 NServiceBus 时如何防止“System.Transactions.TransactionException”错误
- comments - 在 textwrangler 中阻止评论 Haskell 代码
- java - 材质日历视图高度换行问题
- android - 通过在 Android/iOS 中使用 GeoCoding API 减少 Google 地方信息的使用
- python - 为什么我不能在 Tornado 中同时请求?
- tcl - 获取已编译 tcl 的配置标志
- kotlin - Kotlin 编译器:数据绑定错误,找不到方法