首頁  >  文章  >  後端開發  >  為什麼在 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