1

我知道 C 标准的以下摘录中提出的 C 链接规则:

1/ 在不同范围内或在同一范围内多次声明的标识符可以通过称为链接的过程来引用同一对象或函数。有三种联系方式:外部、内部和无。

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

3/ 如果对象或函数的文件范围标识符的声明包含存储类说明符 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 */
4

1 回答 1

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 是强制执行的 - 稍后的声明是指在第一个声明中定义的链接。换句话说,带变量的 case 不起作用,因为它们是对象并且涉及到暂定的定义规则。至少标准包含明确的示例,清楚地解释了委员会想要说的内容。

于 2013-10-05T17:56:00.997 回答