双下划线(__const)在C中意味着什么?

问题描述 投票:46回答:4
extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr)
 __THROW;

我在Linux机器上的/usr/include/netinet/ether.h中找到了上面的函数定义。

有人可以在const(关键字),addr(标识符)和最后__THROW前面解释双下划线的含义。

c syntax double-underscore
4个回答
68
投票

在C中,以下划线开头,后跟大写字母或另一个下划线的符号保留给实现。您作为C的用户不应创建任何以保留序列开头的符号。在C ++中,限制更严格;用户可能无法创建包含双下划线的符号。

鉴于:

extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr)
__THROW;

__const表示法允许这种代码使用的编译器支持原型符号但不能正确理解C89标准关键字const的可能性(有些不太可能)。 autoconf宏仍然可以检查编译器是否对const有工作支持;此代码可以与没有该支持的损坏的编译器一起使用。

使用__hostname__addr是标题用户的保护措施。如果使用GCC和-Wshadow选项进行编译,编译器将在任何局部变量影响全局变量时发出警告。如果函数只使用hostname而不是__hostname,并且如果你有一个名为hostname()的函数,那就会有阴影。通过使用为实现保留的名称,与您的合法代码不会发生冲突。

使用__THROW意味着在某些情况下,代码可以用某种“抛出规范”声明。这不是标准C;它更像是C ++。但是代码可以与C编译器一起使用,只要其中一个头(或编译器本身)将__THROW定义为空,或者定义为标准C语法的某些特定于编译器的扩展。


C标准(ISO 9899:1999)第7.1.3节说:

7.1.3 Reserved identifiers

每个标头声明或定义其关联子条款中列出的所有标识符,并可选地声明或定义其关联的未来库方向子条款和标识符中列出的标识符,这些标识符始终保留用于任何用途或用作文件范围标识符。

- 所有以下划线开头的标识符以及大写字母或另一个下划线始终保留用于任何用途。

- 所有以下划线开头的标识符始终保留用作普通和标记名称空间中具有文件范围的标识符。

- 如果包含任何相关标头,则保留以下任何子条款中的每个宏名称(包括未来的库方向)以供指定使用;除非另有明确说明(见7.1.4)。

- 以下任何子条款中包含外部链接的所有标识符(包括未来的库方向)始终保留用作具有外部链接的标识符.154)

- 如果包含任何相关标头,则保留下列任何子条款(包括未来库方向)中列出的具有文件范围的每个标识符,以用作宏名称和具有相同名称空间的文件范围的标识符。

没有保留其他标识符。如果程序在保留它的上下文中声明或定义标识符(除了7.1.4允许的标识符),或者将保留标识符定义为宏名称,则行为是未定义的。

如果程序删除(使用#undef)上面列出的第一个组中的标识符的任何宏定义,则行为是未定义的。

脚注154)具有外部链接的保留标识符列表包括errnomath_errhandlingsetjmpva_end


另见What are the rules about using an underscore in a C++ identifier;许多相同的规则同样适用于C和C ++,尽管嵌入式双下划线规则仅适用于C ++,如本答案顶部所述。


19
投票

具有双前导下划线的名称保留供实现使用。这并不一定意味着它们本身就是内在的,尽管它们通常是。

这个想法是,你不允许使用任何以__开头的名字,所以实现可以在宏扩展或者语法扩展的名称中自由使用它们(例如__gcnew不是C ++的一部分,但是微软可以将它添加到C ++ / CLI,确信没有现有的代码应该有类似int __gcnew;的东西,它会停止编译)。

要了解这些特定扩展的含义,即__const,您需要查阅特定编译器/平台的文档。在这种特殊情况下,您可能应该将文档中的原型(例如http://www.kernel.org/doc/man-pages/online/pages/man3/ether_aton.3.html)视为函数的接口,并忽略实际标题中出现的__const__THROW装饰。


3
投票

按照惯例,在某些库中,这表示特定符号供内部使用,并不打算成为库的公共API的一部分。


2
投票

__const中的下划线表示此关键字是编译器扩展,并且使用它不可移植(在以后的版本中,const关键字被添加到C中,89我认为)。 __THROW也是某种扩展,我假设它被定义为某些__attribute __(某些东西)如果使用gcc,但是我不确定那个并且懒得检查。 __addr可以表示程序员想要的任何意思,它只是一个名字。

© www.soinside.com 2019 - 2024. All rights reserved.