在gcc中似乎允许使用局部函数声明,我对此进行了讨论:Is there any use for local function declarations?
但是,我的问题是:ISO C标准是否允许?如果是这样,如何解释以下令人费解的现象:
int main(void) {
int f(void);
f();
}
void g(void) {
/* g has no idea about f. It seems that the decl is limited within its
* scope */
f();
}
int f(void) {}
而
int main(void) {
int f(void);
f();
}
void f(void); /* error because disagreement with the local declaration (local
declaration goes beyound its scope?) */
void f(void) { /* definition here */ }
根据C99标准:函数名称在同一命名类别中。因此,我们将讨论范围界定机制以对此进行解释。但是如何?
实际上,我正在从事一个编译器课程项目,该项目要求我们实现C编译器的简化版本。我试图处理此案,但感到困惑。
编辑:我知道C是面向过程的,并且要求函数名称是唯一的,这是众所周知的。但是这种地方性的声明引起了明显的局面,我很难理解其原则/规则。
最佳答案
ISO C和C ++都允许局部函数声明。在每种情况下,函数声明的作用域都在本地作用域的末尾结束。但是,函数声明及其定义具有外部链接,因此链接器仍然需要接受它们。
在您的示例中:
int main(void) {
int f(void);
f();
}
void f(void);
void f(void) { }
该代码可以像C或C ++一样正确编译。在C中通常应该链接,但在C ++中则不应该链接(因为“类型安全链接”)。
int f(void);
将有一个未解决的外部。[如果由于英语难而无法回答您的问题,请澄清,我将编辑答案。]
C标准包含以下内容。 n1570 / S6.7.1 / 7:
具有块范围的函数的标识符的声明应没有显式
除extern外的存储类说明符。
显然,明确允许使用局部函数声明。
关于外部链接的n1570 S6.2.2 / 5:
如果函数的标识符声明没有存储类说明符,则其链接
完全确定,就像使用存储类说明符extern声明了它一样。如果
对象标识符的声明具有文件范围,并且没有存储类说明符,
它的联系是外部的。
因此,局部函数声明具有外部链接。这很明显:如果他们有内部链接或没有链接,则它们将无法链接到任何东西。