我一直在研究glibc的一些源代码,特别是nptl代码,我发现它有点难以理解,因为它似乎有我不熟悉的约定。 / p>
例如,我正在查看一个非常小的文件pthread_equal.c,我有一些问题:
22 int
23 __pthread_equal (thread1, thread2)
24 pthread_t thread1;
25 pthread_t thread2;
26 {
27 return thread1 == thread2;
28 }
29 strong_alias (__pthread_equal, pthread_equal)
第22和23行的声明看起来像我理解的东西。它的返回类型为int
,然后是函数名__pthread_equal
和参数列表(thread1, thread2)
。但第24行pthread_t thread1;
和25 pthread_t thread2;
的声明是什么?看起来这些被声明为全局变量,但我不明白其目的。我在nptl目录中的许多文件中都看到了这种模式,并且无法弄清楚为什么会这样做。
什么是strong_alias
?一个快速的谷歌搜索有使用这个的例子,但我没有找到任何文档的链接。
使用两个下划线__
为某些名称添加前缀的原因是什么,有些下划线为_
。我见过的大多数代码使用了两个下划线,但我想我已经看到了一些使用下划线的地方。例如在pthreadP.h
556 /* Old cleanup interfaces, still used in libc.so. */
557 extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
558 void (*routine) (void *), void *arg);
559 extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
560 int execute);
561 extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
562 void (*routine) (void *), void *arg);
563 extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
564 int execute);
不可否认,代码前面带有一个注释,上面写着“旧的清理界面”,但无论哪种方式,我都对这种差异感到好奇,为什么有时会使用一个下划线,有时会使用两个下划线。
有关这些问题的任何信息都表示赞赏。
答案 0 :(得分:9)
编写该函数时无需符合C89标准的编译器;它也适用于较旧的编译器。这是一个非原型函数定义。
int /* Return type */
function(arg1, arg2) /* Function name and argument names (but no types) */
int arg1; /* Type of arg1 */
char *arg2; /* Type of arg2 */
{
/* Body of function */
}
请注意,参数的定义不必与函数行中的序列相同(我必须将代码从此'K& R'表示法转换为原型表示法,而不是它们出现故障! )。另请注意,以前可以简单地写一下:
main(argc, argv)
char **argv;
{
...
}
argc
的隐含类型为int
,因为它未被指定为其他任何内容。 glib
代码不太可能利用该许可证。同样,main()
的返回类型为int
,因为没有给出其他类型。
strong_alias
与隐藏和公开共享库中的符号有关。我没有使用它,所以我不确定所有后果,但我认为这意味着__pthread_equal()
是pthread_equal()
函数的另一个名称。
__pthread_equal()
名称背后的推理的一部分是,以下划线开头,后跟大写字母或另一个下划线的名称由C标准“保留给实现”。根据C标准,诸如'pthread_equal()'之类的名称位于用户的名称空间中。
ISO / IEC 9899:1990(C99标准)说:
7.1.3保留标识符
每个标头声明或定义其相关子条款中列出的所有标识符,以及 可选地声明或定义其关联的未来库方向中列出的标识符 子条款和标识符,它们总是保留用于任何用途或用作文件 范围标识符。
- 所有以下划线和大写字母或其他字母开头的标识符 下划线总是保留用于任何用途。
- 所有以下划线开头的标识符始终保留用作标识符 在普通名称和标签名称空间中都有文件范围。
- 以下任何子条款中的每个宏名称(包括未来的库 如果包含任何相关标题,则保留指定用途; 除非另有明确说明(见7.1.4)。
- 以下任何子条款中包含外部链接的所有标识符(包括 未来的图书馆方向)始终保留用作外部标识符 键。 154)
- 具有文件范围的每个标识符在以下任何子条款中列出(包括 未来的图书馆方向)保留用作宏名称和标识符 如果包含任何相关标头,则文件范围在同一名称空间中。
不保留其他标识符。如果程序声明或定义了一个标识符 保留的上下文(7.1.4允许的除外),或定义保留的上下文 标识符作为宏名称,行为未定义。
154)包含外部链接的保留标识符列表包括
errno
,math_errhandling
,setjmp
和va_end
。
答案 1 :(得分:2)
__pthread_equal
,pthread_equal
的类型相同。