![](/img/trans.png)
[英]In C, if objects declared at block scope have no linkage, why does function declaration inside main() without “extern” work?
[英]C function declaration linkage
我对C17 标准中的一个主题有点困惑。
在 6.2.2 的第 5 点中,您可以阅读:
如果函数标识符的声明没有存储类说明符,则它的链接将完全确定,就好像它是使用存储类说明符 extern 声明的一样。 [...]
这意味着它可以具有内部或外部链接,具体取决于该函数之前的其他声明(如果有)。
另一方面,在 6.7.6.3 示例 1(第 16 和 17 点)中,您可以阅读:
int f(void), *fip(), (*pfi)();
[...]
如果声明出现在任何函数之外,则标识符具有文件范围和外部链接。 [...]
所以, pfi
没问题(它不是一个函数,而是一个指针),但是f
和fip
会发生什么? 这不是矛盾吗? 在 6.2.2 中,它“好像存在外部存储类说明符”(这并不总是意味着它将具有外部链接),但在 6.7.6.3 中,外部链接似乎是理所当然的。
我错过了什么?
编辑:更具体地说,如果我们在文件范围内有此代码:
// One random "previous declaration":
static int f(void); // declares internal linkage
// Now, the important line, from the initial example:
int f(void); // Internal linkage? External linkage?
6.2.2 声明第二个声明具有内部链接。
6.7.6.3 声明第二个声明具有外部链接。
C 2018 6.7.6.3 16 中的示例代码旨在成为没有事先声明的独立代码,或者 C 2018 6.7.6.3 17 中文本的作者表示“如果声明发生在任何函数之外,则标识符具有文件范围和外部链接”忽略了这样一个事实,即f
可能由于先前的static
声明而具有内部链接,并且此新声明将保留该先前的链接。
如问题中所述,C 2018 6.2.2 5 说“如果函数的标识符声明没有存储类说明符,则其链接的确定与使用存储类说明符extern
声明时完全相同......”不是在问题中指出,6.2.2 4 说“对于使用存储类说明符extern
在该标识符的先前声明可见的范围内声明的标识符,如果先前声明指定内部或外部链接,则后面声明的标识符与前面声明中指定的链接相同……”当然我们知道 6.2.2 3 告诉我们“如果对象或函数的文件范围标识符的声明包含存储类说明符static
,标识符具有内部链接。”
因此,如果示例代码int f(void), *fip(), (*pfi)();
在先前的文件范围static int f(void);
可见,则示例代码中的f
具有内部链接。
因此,C 2018 6.7.6.3 17 说f
必然具有外部链接是错误的,除非该示例旨在成为没有事先声明的独立代码。 此外,6.7.6.3 17 是示例文本,并且“在 ISO 标准中,示例无一例外是非规范性的。” 上面引用的其他文本是规范文本,因此具有约束力,而 6.7.6.3 17 中的示例文本则没有。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.