为什么C预处理器将单词“linux”解释为常量“1”?

为什么GCC中的C预处理器将linux(小写字母)解释为常量1

test.c:

#包括<标准h>
内部主(空)
{       
int-linux=5;
返回0;
}

$gcc-E test.c的结果(在预处理阶段后停止):

。。。。
内部主(空)
{
int 1=5;
返回0;
}

这当然会产生一个错误

(顺便说一句:stdio.h文件中没有#define linux

在过去(ANSI之前),预定义符号(如unixvax)是一种允许代码在编译时检测其编译目的系统的方法。当时没有官方语言标准(除了《K&R》第一版后面的参考资料之外),任何复杂的C代码通常都是由#ifdef组成的复杂迷宫,以考虑系统之间的差异。这些宏定义通常由编译器本身设置,而不是在库头文件中定义。由于没有关于实现可以使用哪些标识符以及哪些标识符是为程序员保留的真正规则,编译器编写人员可以随意使用简单的名称,如unix,并假设程序员只是为了自己的目的而避免使用这些名称

1989年的ANSI C标准引入了限制实现可以合法预定义的符号的规则。编译器预定义的宏的名称只能以两个下划线开头,或以下划线后跟大写字母开头,这样程序员就可以自由地使用与该模式不匹配且未在标准库中使用的标识符

因此,任何预定义unixlinux的编译器都是不符合要求的,因为它无法编译使用int linux=5之类的东西的完全合法的代码

实际上,gcc在默认情况下是不一致的——但是可以使它(相当好地)符合正确的命令行选项:

gcc-std=c90-pedantic…#或-std=c89或-ansi
gcc-std=c99-迂腐
gcc-std=c11-迂腐

有关更多详细信息,请参阅gcc手册

gcc将在未来的版本中逐步淘汰这些定义,所以您不应该编写依赖于它们的代码。如果您的程序需要知道它是否是为Linux目标编译的,它可以检查是否定义了\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(假设您使用的是gcc或与之兼容的编译器)。有关更多信息,请参阅GNUC预处理器手册

一个基本上不相关的旁白:1987年国际模糊C代码大赛的“最佳一行”冠军由David Korn(是的,Korn Shell的作者)利用预定义的unix宏:

main()

它打印“unix”,但原因与宏名称的拼写完全无关

发表评论