首页 > 解决方案 > 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 == 0is true)?

例如,在IEEE 754NaN 中可以看作UNDEFINED(Not a Number, 因此,没有数字,数字未定义,即未定义) 并且NaN == 0false

#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 的动机是什么?

标签: clanguage-lawyerundefinedc-preprocessornan

解决方案


问题:在 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

推荐阅读