c - C预处理器:将未定义的宏视为0的动机是什么?
问题描述
ISO/IEC 9899:202x (E) 工作草案 — 2020 年 2 月 5 日 C17..C2x N2479:
由于宏扩展和定义的一元运算符的所有替换都执行完毕后,所有剩余的标识符(包括那些在词法上与关键字相同的标识符)都被替换为 pp-number 0,然后将每个预处理标记转换为一个标记。
换句话说:
未定义为宏的标识符在计算表达式之前转换为 0。
这导致了这样一个UNDEFINED == 0
事实:
#if UNDEFINED == 0
#pragma message "UNDEFINED == 0 is true"
#endif
$ gcc t0.c -E
t0.c:3:9: note: '#pragma message: UNDEFINED == 0 is true'
但是,如何在概念上(逻辑上、数学上、哲学上等)UNDEFINED
等于0
(导致UNDEFINED == 0
is true
)?
例如,在IEEE 754
NaN 中可以看作UNDEFINED
(Not a Number, 因此,没有数字,数字未定义,即未定义) 并且NaN == 0
是false
:
#include <stdio.h>
#include <math.h>
int main( void )
{
printf("NaN == 0 is %d\n", NAN == 0);
return 0;
}
$ gcc t0.c && ./a.exe
NaN == 0 is 0
问题:在 C 预处理器中将未定义宏视为 0 的动机是什么?
解决方案
问题:在 C 预处理器中将未定义宏视为 0 的动机是什么?
强调预处理器。未定义的宏被0
预处理器处理,但不被编译器处理。例如,以下代码无法编译:
#undef UNDEFINED
#if UNDEFINED == 0 // ok, preprocessor evaluates this as '0 == 0'
int n = UNDEFINED; // error, compiler sees this as 'int n = <undeclared-identifier>;'
#endif
与其他特质一样,“为什么”问题的真正答案是“因为 C 语言标准是这样说的”。虽然很难追查几十年前的原始动机,但这种行为实际上确实简化了某些构造,例如以下足以检查 C99 合规性,而不必担心标准宏 __STDC_VERSION__
是否由实现定义:
#if __STDC_VERSION__ >= 199901L
// safely assume C99 or later
#else
// either __STDC_VERSION__ is not defined
// or it is earlier than C99
#endif
推荐阅读
- c# - DI。将接口添加到 AuthController 构造函数后未命中登录操作
- java - 无法初始化类 weblogic.utils.LocatorUtilities$Locator
- java - Spring @Validated - 具有一组超级值
- django - django 后端和角度前端向后端发送请求
- java - 加载后瞬态字段不为空
- ruby-on-rails - Rails 在渲染集合时如何知道要渲染哪个部分名称?
- ffmpeg - AV_CODEC_FLAG2_FAST 在解码 H.264 中的作用
- python - Python:pos标签-带有单词'back'
- android - 启动应用程序时出错:未找到默认活动 - 两次中的一次
- vb.net - 如何使用图形模糊 DrawLine?