c - 为什么编译器认为 GCC 中嵌套函数(GNU 扩展)的地址为 "not constant"?

标签 c gcc gnu nested-function static-initialization

GNU C 编译器包含一个很好的 C 语言扩展,称为 Nested Functions .
但是,文档在某些方面尚不清楚。例如,它说

It is possible to call the nested function from outside the scope of its name by storing its address or passing the address to another function [...]

If you try to call the nested function through its address after the containing function exits, all hell breaks loose.

If you try to call it after a containing scope level exits, and if it refers to some of the variables that are no longer in scope, you may be lucky, but it’s not wise to take the risk.

If, however, the nested function does not refer to anything that has gone out of scope, you should be safe.


所以一方面,它说如果你在包含函数退出后调用嵌套函数,“所有的 hell 都会崩溃”,但前面几句话它说在某些情况下这样做是可以的。
我想“超出范围的事情”是指自动变量,因此特别是重构应该是安全的
static int f() { ... }

int outer() {
    ... // some use of f
}
进入
int outer() {
    int f() { ... } // f does not refer to outer's local variables
    ... // some use of f
}
如果 f 没有其他用途在模块中比在 outer 中的那些函数,即使假设 outer函数以某种方式泄露了 f 的地址超出了自己的范围。
但是,我惊讶地发现以下代码无法编译
int main(void) {
    void nested_function(void) {}

    static const struct { void (*function_pointer)(void); } s = {
        .function_pointer = nested_function
    };

    return 0;
}
投诉initializer element is not constant (即 nested_function )。
这种限制有什么理由吗? (我无法想象一个函数的地址是非常量的,即使它是嵌套的)

最佳答案

在当前的 GCC 实现中,嵌套函数的不必要的静态链指针仅在优化期间被省略。它不会反射(reflect)在类型系统中(与不绑定(bind)任何内容的 C++ lambda 不同)。如果没有优化,编译器必须在堆栈上创建一个蹦床,所以在这种情况下函数地址实际上是非常量的。

关于c - 为什么编译器认为 GCC 中嵌套函数(GNU 扩展)的地址为 "not constant"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60548397/

相关文章:

android - 优化我的内部循环(ARM,android ndk)

c - 没有进程区域设置的 Gettext

c++ - GetProcAddress 与所有加载的库

c - 保持输出为零

linux -/usr/bin/ld : skipping incompatible foo. 所以在搜索 foo 时

c - PDCurses 无法在 Windows 上编译

bash - 如何使用 GNU 并行

c - opendir:打开的文件太多

c++ - Linux 编译错误 - GCC 4.3.4 - 模板参数列表太少

c - GCC 在编译时不发出警告