默认情况下函数是外部的吗?

Are functions external by default?

是一个没有在其声明和定义中指定存储class的函数:

void func(void); // declaration

void func(void) { // implementation
    
}

相当于在其声明和定义中带有外部存储class的函数? :

extern void func(void); // declaration

extern void func(void) { // implementation
    
}

来自 C 标准(6.2.2 标识符的链接)

5 If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.

默认情况下,函数标识符始终具有外部链接。存储 class 是一个单独的问题。

关于声明的一些规则是:

  • 对于函数外的声明,默认情况下所有标识符都有外部链接。

  • 对于函数内部的声明,函数的标识符默认有外部链接,对象的标识符默认没有链接。

  • 如果声明包含static,标识符有内部链接。

根据这些规则,函数的标识符默认具有外部链接,如果使用 static 声明则具有内部链接,并且绝不会没有链接。还有一些额外的声明规则,这里没有完全描述。由于 C 语言的发展历史,这些规则很杂乱而且有点复杂。不同的 C 实现以不同的方式做事,C 标准化委员会必须将事情联系在一起。

函数没有存储 classes。存储 classes,或者更准确地说,存储持续时间,是对象生命周期的类别。 externstatic 是称为 storage-class 说明符的关键字,与存储 classes 不同(同样“fox”和“dog”是动物词,但不是动物)。 Storage-class 说明符部分影响对象的存储 classes,但它们也影响标识符和其他事物的链接。函数标识符的链接是这里的问题,而不是存储 class。链接是一个过程,通过该过程可以使在不同位置声明相同的标识符来引用相同的对象或函数。由于 C 历史的复杂性,extern 关键字导致新声明中标识符的外部链接,而 static 导致内部链接。 (在可见标识符的重新声明中,extern 不会更改先前的链接;在 static int x; extern int x; 中,x 仍然在后者中具有内部链接。如上所述,规则很复杂。)