在gcc中有作为内置macros的非保留标识符的原因是什么?

今天我偶然发现了一个相当有趣的编译器错误:

int main() { int const unix = 0; // error-line return unix; } 

给gcc 4.3.2(是的,古老的)以下消息:

 error: expected unqualified-id before numeric constant 

这绝对是相当混乱。

幸运的是,铿锵声(3.0)是一个更有帮助(像往常一样):

 error: expected unqualified-id int const unix = 0 ^ <built-in>:127:14: note: expanded from: #define unix 1 ^ 

我当然没有想到unix ,它既不是大写字母,也不是从下划线开始,成为一个macros,特别是一个内置macros。

我检查了gcc中的预定义macros,并且有2个(在我的平台上)使用“非保留”符号:

 $ g++ -E -dM - < /dev/null | grep -v _ #define unix 1 #define linux 1 

所有其他的都是带有下划线的“行为良好”的macros,使用传统的保留标识符,示例:

 #define __linux 1 #define __linux__ 1 #define __gnu_linux__ 1 #define __unix__ 1 #define __unix 1 #define __CHAR_BIT__ 8 #define __x86_64 1 #define __amd64 1 #define _LP64 1 

(这是一团糟,似乎没有任何特定的顺序…)

此外,还有很多“相似”的符号,所以我想这是一个向后兼容的问题。

那么, unixlinuxmacros从何而来呢?

Solutions Collecting From Web of "在gcc中有作为内置macros的非保留标识符的原因是什么?"

gcc默认不完全符合任何C标准。

-ansi-std=c99-std=c1x调用它, unix不会被预定义。 ( -std=c1x 可能会未来的更新的gcc版本中变成-std=c11 )。

这有点令人困惑,这是在GNU预处理器的单独手册中记录的,而不是在gcc手册中。

引用GNU预处理器文档( info cpp ,版本4.5):

C标准要求所有系统特定的宏都是“保留名称空间”的一部分。 所有以两个下划线或下划线和大写字母开头的名字都是为编译器和库保留的,只要他们愿意就可以使用。 但是,历史上系统特定的宏名称没有特殊的前缀; 例如,在Unix系统上定义`unix'是很常见的。 对于所有这样的宏,GCC提供了一个在开始和结尾处添加了两个下划线的并行宏。 如果定义了“unix”,则也会定义“__unix__”。 永远不会有两个以上的下划线; `_mips'的并行是`__mips__'。

当编译器给出`-ansi'选项或任何请求严格一致性的`-std'选项时,保留的名称空间之外的所有系统特定的预定义宏都被禁止。 保留名称空间内的并行宏保持定义。

我们正在慢慢地逐步淘汰保留名称空间之外的所有预定义的宏。 您不应该在新程序中使用它们,并且我们鼓励您在更新代码时使用并行宏。 我们不建议您使用保留名称空间中的系统特定的宏。 从长远来看,使用“autoconf”这样的工具来更好地检查你需要的功能。

手册的当前版本在这里 。