我知道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 */
答案 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是强制执行的 - 后面的声明是指第一个声明中定义的链接。换句话说,变量的情况不起作用,因为它们是对象,并且涉及暂定的定义规则。至少标准包含明确解释委员想说的内容的明确例子。