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

时间:2009-09-19 18:32:50

标签: c syntax double-underscore

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

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

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

4 个答案:

答案 0 :(得分: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 ++。但是只要其中一个头(或编译器本身)将__THROW定义为空,或者对标准C语法的某些特定于编译器的扩展,代码就可以与C编译器一起使用。


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

  

7.1.3保留标识符

     

每个标头声明或定义其相关子条款中列出的所有标识符,以及   可选地声明或定义其关联的未来库方向中列出的标识符   子条款和标识符,它们总是保留用于任何用途或用作文件   范围标识符。

     

- 所有以下划线和大写字母或其他字母开头的标识符   下划线总是保留用于任何用途。

     

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

     

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

     

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

     

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

     

不保留其他标识符。如果程序声明或定义了一个标识符   保留的上下文(7.1.4允许的除外),或定义保留的上下文   标识符作为宏名称,行为未定义。

     

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

     

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


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

答案 1 :(得分:19)

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

这个想法是,你不允许使用以__开头的任何名字,所以实现可以在宏扩展的地方或语法扩展的名称中使用它们(例如{{{{ 1}}不是C ++的一部分,但是微软可以将它添加到C ++ / CLI,确信现有的代码中不应该包含__gcnew之类的内容,这样会停止编译)。

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

答案 2 :(得分:3)

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

答案 3 :(得分:2)

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