首頁  >  文章  >  後端開發  >  為什麼不同翻譯單元中的全域變數會導致 C 中的意外行為?

為什麼不同翻譯單元中的全域變數會導致 C 中的意外行為?

Barbara Streisand
Barbara Streisand原創
2024-10-30 02:51:28947瀏覽

 Why Can Global Variables in Different Translation Units Lead to Unexpected Behavior in C  ?

C 中的全域初始化順序與相依解析

在C 中,單一翻譯單元內的全域變數依照定義的順序進行初始化。然而,不同翻譯單元之間的全域變數沒有明確定義的順序。這種歧義可能會導致意外的行為,如以下程式碼所示:

<code class="cpp">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();</code>

當在初始化globalFoo 之前調用addToGlobal 時,行為符合預期:

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

但是,當當順序顛倒時,不會呼叫Foo 的建構函數,並且可以在addToGlobal 中以某種方式存取 globalFoo:

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

此行為歸因於以下事實:全域變數的初始化順序忽略了它們之間的任何依賴關係。在這種情況下,dummy 依賴 globalFoo,但不能保證它們的初始化順序。

為了確保在使用 globalFoo 之前呼叫 Foo 的建構函數,一種解決方案是建立一個指向全域實例的靜態指標並進行測試addToGlobal 中是否為 null。如果為 null,則在任何動態初始化之前建立全域 Foo。

以上是為什麼不同翻譯單元中的全域變數會導致 C 中的意外行為?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn