在gcc中将未保留的标识符作为内置宏的原因是什么? [英] What is the reason for having unreserved identifiers as built-in macros in gcc?

查看:218
本文介绍了在gcc中将未保留的标识符作为内置宏的原因是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

使用gcc 4.3.2提供以下消息):

 错误:数字常量之前的预期未限定标识符

这确实令人困惑。



幸运的是,clang(3.0) :

 错误:expected unqualified-id 
int const unix = 0
^
< ;内置>:127:14:注:扩展自:
#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默认不完全符合任何C标准。 >

使用 -ansi -std = c99 -std = c1x unix 不会预定义。 ( -std = c1x 可能会变成 -std = c11 > 更新的gcc版本。)



这有点混乱,这在GNU预处理器的单独手册中记录,而不是在gcc手册。



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


C标准要求所有系统特定的宏都是
reserved namespace的一部分。以两个下划线
或下划线和大写字母开头的所有名称都保留给编译器
和库,以供他们使用。然而,历史上
系统特定的宏具有没有特殊前缀的名称;对于
实例,通常在Unix系统上找到定义的`unix'。对于
所有这样的宏,GCC提供一个并行宏,在开头和结尾添加两个下划线
。如果定义了`unix',
`__unix__'也将被定义。将不会有超过两个
下划线; <_ p>

当`-ansi'选项或任何要求严格
一致性的`-std'选项时,给予编译器,在保留的命名空间之外的所有系统特定的
预定义宏被抑制。在保留的命名空间内的
并行宏仍然被定义。



我们正在慢慢地逐步删除在
保留命名空间之外的所有预定义的宏。你不应该在新程序中使用它们,我们
鼓励你更正旧的代码,使用并行宏
,当你找到它。我们不建议您使用保留的命名空间中的系统特定的
宏。在
中,最好是使用工具
(例如`autoconf')来专门检查所需的功能。


手册的当前版本为此处


Today I stumbled upon a rather interesting compiler error:

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

Gives the following message with gcc 4.3.2 (yes, ancient...):

error: expected unqualified-id before numeric constant

which is definitely quite confusing.

Fortunately, clang (3.0) is a little more helpful (as usual):

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

I certainly did not expect unix, which is neither written in upper-case nor begin with underscore to be a macro, especially a built-in one.

I checked the predefined macros in gcc and there are 2 (on my platform) that use "unreserved" symbols:

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

All the others are "well-behaved" macros with leading underscores, using the traditional reserved identifiers, sample:

#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

(it's a mess and there does not seem to be any particular order...)

Furthermore, there are lots of "similar" symbols, so I guess there is an issue of backward compatibility...

So, where do the unix and linux macros come from ?

解决方案

gcc does not fully conform to any C standard by default.

Invoke it with -ansi, -std=c99, or -std=c1x and unix won't be predefined. (-std=c1x will probably become became -std=c11 in a future more recent gcc release.)

It's a bit confusing that this is documented in the separate manual for the GNU preprocessor, not in the gcc manual.

Quoting the GNU preprocessor documentation (info cpp, version 4.5):

The C standard requires that all system-specific macros be part of the "reserved namespace". All names which begin with two underscores, or an underscore and a capital letter, are reserved for the compiler and library to use as they wish. However, historically system-specific macros have had names with no special prefix; for instance, it is common to find `unix' defined on Unix systems. For all such macros, GCC provides a parallel macro with two underscores added at the beginning and the end. If `unix' is defined, `__unix__' will be defined too. There will never be more than two underscores; the parallel of `_mips' is `__mips__'.

When the `-ansi' option, or any `-std' option that requests strict conformance, is given to the compiler, all the system-specific predefined macros outside the reserved namespace are suppressed. The parallel macros, inside the reserved namespace, remain defined.

We are slowly phasing out all predefined macros which are outside the reserved namespace. You should never use them in new programs, and we encourage you to correct older code to use the parallel macros whenever you find it. We don't recommend you use the system-specific macros that are in the reserved namespace, either. It is better in the long run to check specifically for features you need, using a tool such as `autoconf'.

The current version of the manual is here.

这篇关于在gcc中将未保留的标识符作为内置宏的原因是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆