c - 什么是 C 局部函数声明机制?

标签 c compiler-construction scope function-declaration

局部函数声明似乎在 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标准:函数名属于同一个命名范畴。因此,我们将讨论范围界定机制来解释这一点。但是如何呢?

实际上,我正在从事一个编译器类(class)项目,该项目要求我们实现 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:

The declaration of an identifier for a function that has block scope shall have no explicit storage-class specifier other than extern.

显然局部函数声明是明确允许的。


n1570 S6.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.

因此局部函数声明具有外部链接。这是显而易见的:如果它们有内部链接或没有内部链接,它们将无法链接到任何内容。

关于c - 什么是 C 局部函数声明机制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22904848/

相关文章:

c - 标量初始值设定项 c 中的多余元素

c++ - Bison Grammar 分解重复的标记/表达式?

javascript - 如何从 API 获取结果并将其存储为全局变量?

java - 每秒更新 TextView 中的数字

java - 我可以使用来自 Javascript 的 V8 引擎来执行带有 Flash 用户界面的 C 或 C++ 或 JNI 函数吗?

c - 错误 1 ​​在 C 中使用 gcc 编译和其他错误

c - 访问未对齐的结构成员

c - 为什么编译器不在堆栈上分配和释放具有 "sub*"和 "add*"的局部变量?

javascript - 当引用脱离 JavaScript 中的上下文时,按引用捕获是否会变成按值捕获?

c - Waitpid 的行为就像处于非阻塞模式