【发布时间】:2012-01-30 10:24:57
【问题描述】:
今天我偶然发现了一个相当有趣的编译器错误:
int main() {
int const unix = 0; // error-line
return unix;
}
在 gcc 4.3.2 中给出以下信息(是的,古老的...):
error: expected unqualified-id before numeric constant
这绝对令人困惑。
幸运的是,clang (3.0) 更有帮助(和往常一样):
error: expected unqualified-id
int const unix = 0
^
<built-in>:127:14: note: expanded from:
#define unix 1
^
我当然没想到unix,既不是大写也不是下划线开头的宏,尤其是内置宏。
我检查了 gcc 中的预定义宏,有 2 个(在我的平台上)使用“未保留”符号:
$ g++ -E -dM - < /dev/null | grep -v _
#define unix 1
#define linux 1
所有其他都是带有前导下划线的“行为良好”的宏,使用传统的保留标识符,示例:
#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
(乱七八糟,好像没有什么特别的顺序……)
此外,还有很多“相似”的符号,所以我想存在向后兼容性的问题......
那么,unix 和 linux 宏从何而来?
【问题讨论】:
-
在 gcc 4.7 中工作正常,似乎是一些错误 :)
-
我添加了历史标签,我相信它至少是历史的。
-
很高兴知道。通常我看到相反的情况,就像程序员无缘无故(可能是对被禁止的幼稚热情除外)使用像
__MY_INCLUDE_FILE__这样的名字而不是合法的名字来包含警卫。 -
@6502:我不认为这是对禁忌的热情,我认为这是对货物的狂热编程。人们在编译器(或 SDK)提供的头文件中看到了用于包含保护的标识符,并开始这样做。我认为早期的 Windows SDK 对此做出了很大贡献。 MS 一直在清理 Windows SDK 中的这类东西,但早期的损害已经存在了一段时间(我猜其中很多早于 C 标准)。
-
@fge:标识符任何部分的双下划线保留给编译器实现者。开头的保留单下划线后跟大写字母(任何使用)或开头的单下划线后跟小写字母(用于全局标识符)。通过使用禁止的名称,您可能会遇到非常难以调试的问题(例如,您的程序在 main 启动之前就崩溃了,这仅仅是因为您决定命名一个全局变量
_init)。只需在开头避免下划线(它们也很丑陋)并使用例如MYFILE_H_INCLUDED。
标签: c++ linux unix macros history