在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声明了它一样。如果
对象标识符的声明具有文件范围,并且没有存储类说明符,
它的联系是外部的。


因此,局部函数声明具有外部链接。这很明显:如果他们有内部链接或没有链接,则它们将无法链接到任何东西。

10-07 19:50