为什么stdlib.h充满了外部函数原型和gcc的差异

时间:2013-10-05 14:28:45

标签: c extern linkage

我知道C标准中提供的C链接规则:

  

1 /在不同范围或相同范围内声明的标识符   不止一次可以通过引用相同的对象或功能   一个叫做联系的过程。有三种联系:外部,   内部,没有。

     

2 /在构成一个翻译单元和库的集合中   整个程序,每个特定标识符的声明   外部链接表示相同的对象或功能。在一个   翻译单位,每个内部标识符的声明   连接表示相同的对象或功能。每个声明   没有链接的标识符表示唯一的实体。

     

3 /如果声明对象的文件范围标识符或   function包含存储类说明符static,标识符   有内部联系。

     

4 /对于使用存储类说明符extern声明的标识符   在可以看到该标识符的先前声明的范围内,   如果事先声明指定内部或外部联系,则   后面声明中标识符的链接与   在先前声明中指定的联系。如果没有事先声明   可见,或者如果先前的声明指定没有链接,那么   标识符有外部链接。

     

5 /如果函数的标识符声明没有   存储类说明符,其链接确定就像它一样   用存储类说明符extern声明。如果   对象标识符的声明具有文件范围而没有   存储类说明符,其链接是外部的。

     

6 /以下标识符没有链接:声明了标识符   成为对象或功能以外的任何东西;标识符   声明是一个函数参数;一个块的范围标识符   没有存储类说明符extern声明的对象。

     

7 /如果在翻译单元中出现相同的标识符   内部和外部联系,行为未定义。

我理解extern关键字在函数声明之前是可选的,因为它们在默认情况下是外部的,但在stdlib.h中有一些函数原型以extern开头,例如:

extern void qsort (void *__base, size_t __nmemb, size_t __size,
           __compar_fn_t __compar) __nonnull ((1, 4));

此外,为什么gcc在涉及函数和变量时处理第7点中描述的情况。在此示例中,函数foo和变量d都在内部和外部范围内定义,但只有变量定义会引发错误:

static int foo(void); 
int foo(void); /* legal */

static double d;
double d; /* illegal */

1 个答案:

答案 0 :(得分:0)

可以在函数声明之前自由放置或不放置extern,因此可以在某处找到它并不奇怪。关于第二个问题:

C11草案(n1570.pdf)在第159页有与暂定定义有关的例子:

static int i5; // tentative definition, internal linkage
// ...
int i5; // 6.2.2 renders undefined, linkage disagreement
extern int i5; // refers to previous, internal linkage

6.2.2是您发布的内容。因此,它在这种情况下不起作用,因为有两个具有不同联系的暂定定义,因此存在p.7违规。另一方面,它适用于外部说明符(作为示例中的foo函数),因为p.4是强制执行的 - 后面的声明是指第一个声明中定义的链接。换句话说,变量的情况不起作用,因为它们是对象,并且涉及暂定的定义规则。至少标准包含明确解释委员想说的内容的明确例子。