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是面向过程的,并且要求函数名称是唯一的。但是这种地方性的宣言引起了清晰的局面,我很难理解其原则/规则。
答案 0 :(得分:2)
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之外的存储类说明符。
显然,明确允许本地函数声明。
如果函数的标识符声明没有存储类说明符,则其链接 确定与存储类说明符extern声明的完全相同。如果 对象标识符的声明具有文件范围,没有存储类说明符, 它的联系是外部的。
因此本地函数声明具有外部链接。这很明显:如果他们有内部联系或没有联系,他们就无法链接到任何东西。
答案 1 :(得分:0)
要修复第二个示例,您需要在main中使用正确的返回类型
声明f
int main(void) {
void f(void); // function declaration
f(); // calling function
} // scope of f ends here
void f(void) {}
通过这种方式,您可以通知编译器要查找的内容,稍后它会确实找到它。希望它有所帮助。
答案 2 :(得分:0)
本地extern
声明确实像函数之外的声明一样工作,除了范围有限,或者像本地static
声明一样,除了实体可以通过链接从外部访问。
为什么呢?好吧,为什么不呢?它只是将声明的一般规则和extern
说明符推断到特定的上下文中。
我无法(故意)回忆使用本地外部函数声明,但有几次我使用本地extern
变量声明攻击了调试变量。 extern
声明可以放在一些高度嵌套的代码中,并将数据传递给另一个TU中的调试打印机。