首页  >  文章  >  后端开发  >  为什么在 C 中交换全局变量声明会导致意外行为?

为什么在 C 中交换全局变量声明会导致意外行为?

Susan Sarandon
Susan Sarandon原创
2024-10-30 06:38:03778浏览

 Why Does Swapping Global Variable Declarations in C   Lead to Unexpected Behavior?

C 中的全局初始化顺序:忽略依赖关系

在 C 中,翻译单元内全局变量的初始化顺序是明确定义的。但是,全局变量之间的依赖关系可以被忽略,从而导致令人惊讶的行为。

考虑以下代码:

<code class="cpp">struct Foo;

extern Foo globalFoo;

struct Foo {
    Foo() { printf("Foo::Foo()\n"); }
    void add() { printf("Foo::add()\n"); }
    static int addToGlobal() {
        printf("Foo::addToGlobal() START\n");
        globalFoo.add();
        printf("Foo::addToGlobal() END\n");
        return 0;
    }
};

Foo globalFoo;
int dummy = Foo::addToGlobal();

int main() {
    printf("main()\n");
    return 0;
}</code>

使用 GCC 4.4.3 编译时,预期输出为:

Foo::Foo()
Foo::addToGlobal() START
Foo::add()
Foo::addToGlobal() END
main()

这是因为全局变量globalFoo是在调用静态方法Foo::addToGlobal()之前初始化的。但是,如果我们交换 globalFoo 和虚拟声明的顺序,输出将变为:

Foo::addToGlobal() START
Foo::add()
Foo::addToGlobal() END
Foo::Foo()
main()

看起来 Foo 的实例方法是在未构造的实例上调用的。这是因为全局初始化的顺序忽略了依赖关系。

为了确保 Foo 的构造函数在初始化 dummy 之前被调用,我们需要确保在同一翻译单元中 globalFoo 在 dummy 之前定义。或者,我们可以使用指向全局实例的静态指针,该指针在任何动态初始化之前将被初始化为 null。然后 addToGlobal 方法可以检查指针是否为空,并在必要时创建全局 Foo。

以上是为什么在 C 中交换全局变量声明会导致意外行为?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn