我有以下C語言代碼:
void testA() {
int x = 56;
printf("x的地址 = 0x%x - x的值 = %d
",&x,x)。
}
void testB() {
int y;
printf("y的地址 = 0x%x - y的值 = %d
",&y,y)。
}
int main() {
testA()。
testB()。
return 0;
}
列印結果如下:
x的地址=0x61fdec - x的值=56。
y的地址=0x61fdec - y的值=56
為什么testB()的區域變數y與testA()的區域變數x有相同的地址,并且也繼承了它的值?他們甚至不在同一個范圍內,而且沒有一個是全域變數。
uj5u.com熱心網友回復:
這是因為,在TestA函式呼叫結束時,x超出了范圍并被清理掉了。之后,y被創建并分配到相同的記憶體位置。
注意在下面的代碼中,變數有相同的作用域,但它們有不同的地址:
void test() {
int x = 56;
printf("x的地址 = 0x%x - x的值 = %d
",&x,x)。
int y。
printf("y的地址 = 0x%x - y的值 = %d
",&y,y)。
}
int main() {
test()。
return 0;
}
uj5u.com熱心網友回復:
C 2018 6.2.4 2 說:
物件的生命期是指程式執行程序中保證為其保留存盤的部分......
其識別符號被宣告在沒有static或extern的函式內的物件具有自動存盤期限。C實作為它們自動保留記憶體,并自動釋放保留的記憶體。
壽命從執行時開始。
當物件所在的塊的執行開始時(如果它不是一個可變長度的陣列),或者當執行到宣告時(如果它是一個可變長度的陣列),其生命周期就開始了。
當testA的主體開始執行時,記憶體被保留給x。
然后你把56放在x中。
然后函式回傳,x所在的塊停止執行。因此,記憶體不再為它保留。
沒有人會來找你。
沒有人出現并清理該記憶體。無論是在現實世界還是在計算機中,你的媽媽都不會為你打掃衛生。
有人可能會出現并使用該記憶體。他們應該自己初始化它,但是,如果他們不這樣做,他們可能會看到你放入該記憶體的內容。
當testB開始執行時,記憶體被保留給y。由于這些保留區的組織方式,這很容易成為先前為x保留的相同記憶體。那么出現在y中的值可能是你放在x中的同一個值。
當你打開優化時,編譯器可能會重新設計程式并消除這種影響。或者它可能不會。
uj5u.com熱心網友回復:
因為他們可以。
C標準只是要求同時退出的不同的物件有不同的(讀作不相等的)地址。在你的例子中,沒有一個變數x和y可以在同一時間有效。所以實作可以給他們分配相同的地址。
uj5u.com熱心網友回復:
這個問題有兩種完全不同的答案。
一個是,為物件分配地址是 C 實作的作業。 這不是你的作業,而且可以說這不是你所關心的。 在非常廣泛的范圍內,C實作被允許為你的物件分配任何地址,所以你不應該對它分配的任何東西感到驚訝。 一個新進入作用域的物件恰好與一個剛離開作用域的不同物件有相同的地址? 嗯,這就是 "任何事情"。 不是不可能,不是令人驚訝,不是你的問題。
按照同樣的思路,未初始化的變數的初始值是不確定的。 你不知道它可能是什么;它可能是任何東西。 它只是碰巧與之前的函式中的一個變數有相同的值? 同樣,這也是 "任何東西",而且這不是不可能的,不令人驚訝,不是你的問題。
現在,我知道,這是你的不是你的問題。 你在想象,新的變數恰好與之前的變數具有完全相同的地址和完全相同的值,這不僅僅是一個巧合。 你在想象,這一定意味著什么。 所以這就是第二個答案。
許多 C 實作將函式的區域變數存盤在一個堆疊上。 每個變數的地址通常被定義為函式呼叫的堆疊框架中的一個偏移。 當一個函式回傳時,它的堆疊框架被從堆疊中彈出,而當下一個函式被呼叫時,它的堆疊框架將占據堆疊中相同的、新釋放的部分。 因此,如果上一個和下一個函式都有相同型別的變數,它們相對于堆疊框架的偏移量可能是一樣的。 因此,如果上一個和下一個堆疊框架在堆疊的同一位置,那么這些堆疊框架中的變數也將在同一地址。
此外,當一個函式回傳時,盡管它的堆疊框架從堆疊中被彈出,但這并不意味著任何東西實際上被清除了。 而當一個新呼叫的函式分配了它的堆疊框架時,在這一點上也沒有什么被清除。 因此,如果一個函式有一個沒有明確初始化的區域變數,它的實際初始值--也就是我們說的 "不確定 "的值--實際上將是堆疊上剩下的任何位模式,由上一個函式的堆疊框架留下。 因此,如果上一個函式在相同的堆疊幀偏移量上有相同的變數,你可能會發現,瞧,下一個函式的相同偏移量的變數將開始包含與上一個函式的變數相同的值。
但是,這顯然都是偶然的機會,而不是你可以依賴的東西。 你聽到的關于區域變數不保留其值(更不用說另一個函式的值)的說法是完全正確的。 如果你不想讓函式testB中的y這樣的未初始化變數一開始就包含誘人的令人驚訝的值,那么就把它初始化為一個適當的不令人驚訝的值,對testB有意義。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/329586.html
標籤:
