extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr)
__THROW;
我在Linux机器上的/usr/include/netinet/ether.h中找到了上面的函数定义。
有人可以在const(关键字),addr(标识符)和最后__THROW前面解释双下划线的含义。
答案 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)具有外部链接的保留标识符列表包括
errno
,math_errhandling
,setjmp
和va_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可以表示程序员想要的任何意思,它只是一个名字。