为什么GCC中的嵌套函数(GNU扩展)的地址被认为是;“非常数”;由编译器完成?
GNUC编译器包含一个很好的C语言扩展,名为。 然而,文件在某些方面并不清楚。例如,它说 通过存储嵌套函数的地址或将地址传递给另一个函数[…],可以从其名称范围之外调用嵌套函数 如果您试图在包含函数退出后通过其地址调用嵌套函数,那么所有的麻烦都会发生 如果您试图在包含作用域级别退出后调用它,并且如果它引用了一些不再在作用域中的变量,那么您可能很幸运,但冒险是不明智的 但是,如果嵌套函数未引用超出范围的任何内容,则应该是安全的 一方面,它说,如果在包含函数退出后调用嵌套函数,“一切都会崩溃”,但前面几句话说,在某些情况下这样做是可以的 我认为“超出范围的东西”是指自动变量,所以重构应该是安全的为什么GCC中的嵌套函数(GNU扩展)的地址被认为是;“非常数”;由编译器完成?,c,gcc,gnu,nested-function,static-initialization,C,Gcc,Gnu,Nested Function,Static Initialization,GNUC编译器包含一个很好的C语言扩展,名为。 然而,文件在某些方面并不清楚。例如,它说 通过存储嵌套函数的地址或将地址传递给另一个函数[…],可以从其名称范围之外调用嵌套函数 如果您试图在包含函数退出后通过其地址调用嵌套函数,那么所有的麻烦都会发生 如果您试图在包含作用域级别退出后调用它,并且如果它引用了一些不再在作用域中的变量,那么您可能很幸运,但冒险是不明智的 但是,如果嵌套函数未引用超出范围的任何内容,则应该是安全的 一方面,它说,如果在包含函数退出后调用嵌套函数,“一切都会崩溃”,但前
static int f() { ... }
int outer() {
... // some use of f
}
进入
如果模块中除了outer
函数中的f
没有其他用途,即使假定outer
函数以某种方式泄漏f
的地址超出了其自身的范围
然而,我惊讶地发现以下代码没有编译
int main(void) {
void nested_function(void) {}
static const struct { void (*function_pointer)(void); } s = {
.function_pointer = nested_function
};
return 0;
}
投诉初始值设定项元素不是常量
(即嵌套函数
)
这种限制有什么原因吗?(我无法想象函数的地址是非常量的,即使它是嵌套的)在当前的GCC实现中,嵌套函数不必要的静态链指针只在优化过程中被忽略。它没有反映在类型系统中(不像C++的lambda,它不绑定任何东西)。如果没有优化,编译器必须在堆栈上创建一个蹦床,因此在这种情况下函数地址实际上是非常量。第一段提到的是“名称范围外”,而不是函数退出后的地址。也就是说,它可以作为参数从包含函数中传递给另一个函数,该函数具有不同的作用域,并且看不到嵌套函数的名称。
int main(void) {
void nested_function(void) {}
static const struct { void (*function_pointer)(void); } s = {
.function_pointer = nested_function
};
return 0;
}