在旧时代(ANSI之前),预定义符号(如unix
和vax
)是一种允许代码在编译时检测其编译目标系统的方法。当时没有官方的语言标准(超过第一版K & R的参考资料),任何复杂的C代码通常都是复杂的迷宫,以允许系统之间的差异。这些宏定义通常由编译器本身设置,而不是在库头文件中定义。由于没有关于哪些标识符可以被实现使用以及哪些标识符为程序员保留的真实规则,因此编译器作者可以自由使用简单的名称,如unix
,并且假定程序员会简单地避免将这些名称用于他们自己的目的。
1989年ANSI C标准引入了规则,限制实现可以合法预定义的符号。编译器预定义的宏只能有一个以两个下划线开头的名字,或者下划线后跟一个大写字母,这样程序员就可以自由地使用不符合该模式且标准库中没有使用的标识符。
结果,即预定义unix
或linux
是不合格的,因为它将无法编译使用类似int linux = 5;
完全合法的代码的编译器。
碰巧,GCC是不合格默认 - 但它可以制成符合(相当好)用正确的命令行选项:
gcc -std=c90 -pedantic ... # or -std=c89 or -ansi
gcc -std=c99 -pedantic
gcc -std=c11 -pedantic
详情请参阅the gcc manual。
GCC将被逐步淘汰在未来的版本中这些定义,所以你不应该写依赖于他们的代码。如果你的程序需要知道是否它被编译为一个Linux目标或没有它可以检查是否__linux__
定义(假设你使用gcc或与它兼容的编译器)。有关更多信息,请参阅the GNU C preprocessor manual。
一个几乎无关紧要的旁白:1987年International Obfuscated C Code Contest的“最佳一班轮”获得者,由戴维·科恩(是的,Korn Shell程序的作者)了预定义unix
宏的优势:
main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
它打印"unix"
,但出于与宏名称的拼写完全无关的原因。
,你会觉得这个问题/问题早就由现在 – Letseatlunch
相关的问题上来:http://stackoverflow.com/问题/ 3770322/is-unix-restricted-keyword-in-c – matcheek
你有没有试过'#undef linux',或者使用不同的变量?我认为常用的'linux'用于测试操作系统,例如如果你正在设计一个跨平台的应用程序,并且需要知道使用哪个API(windows,mac,linux,BSD等)。它不在stdio.h中,但是如果内核是linux,它仍然是定义的。相同的代码不应该在Windows中产生一个错误,但使用像Windows或Windows作为变量可能会,反之亦然 –