2010-11-24 55 views
1
#include <iostream> 
using std::cout; 
using std::endl; 

int a[] = { 10, 20 }; 

int b[] = { 30, 40 }; 

int main(int argc, char ** argv) 
{ 
int * p = a; 

for (int i = 0; i < 4; i++) 
{ 
    cout << *(p + i) << endl; 
} 

return 0; 
} 

它爲什麼工作?MVSC中陣列的存儲器分配++

+1

你不應該依賴這種行爲。 – 2010-11-24 08:02:41

+0

你是否暗示,該程序不會崩潰? – 2010-11-24 08:02:43

+0

另請參閱:http://stackoverflow.com/questions/671703/array-index-out-of-bound-in-c和http://stackoverflow.com/questions/3658383/accessing-array-beyond-the-限制 – 2010-11-24 08:10:54

回答

4

這是一個典型的例子未定義的行爲Undefined behaviour並不意味着崩潰 - 這意味着未定義的beaviour - 它可以工作,崩潰,不工作,不崩潰,以及幾乎任何其他事情

0

它偶爾的作品。

您的代碼暴露了未定義的行爲,並且在未定義的行爲中,它也有可能顯然「工作」。

1

它會工作(有時),因爲編譯器(有時 - 很好,經常)將數組放在內存中彼此相鄰。從指向第一個數組中第一個位置的指針開始,可以(有時)通過增加指針來遍歷兩個數組。

記憶以這種方式佈置的事實根本不能保證,也不是任何'真實'的程序應該依賴的東西。

由於該標準沒有指定編譯器在這種情況下應如何表現,因此稱爲未定義行爲(UB)。一些信息here

0

我的猜測是,你的輸出是:

10 
20 
30 
40 

你的代碼依賴於未定義行爲:你的情況ab似乎是在內存中連續的,但就是不保證

當達到未定義行爲限制時,任何事情都可能發生。我的意思是說:它可以「工作」,或者它可能會崩潰,或者它可以向古巴發射導彈。

2

C和C++不會在運行時檢查您嘗試訪問的內存位置。您可以訪問陣列之外的存儲單元,這將會起作用。如果以這種方式訪問​​你知道的內存(C++標準或你的編譯器告訴你如何分配的內存),任何事情都可以正常工作(你甚至可以真正這樣做),否則這是一個錯誤,你的應用程序將得到不可預知的行爲。

就你而言,這意味着ab在連續的存儲單元上。無論如何,這隻取決於你的編譯器。如果您使用其他編譯選項,則您的代碼可能無法在不同的編譯器上,不同版本的編譯器上或甚至在同一編譯器上工作。

0

因爲編譯器在內存中分配b權利a。嘗試打印每個循環迭代的實際地址abp,您會看到它很漂亮。這就是在連續行中聲明的變量通常會發生的情況。 但是你不能相信這一點。編譯器優化可以做其他事情。如果您需要確信分配給兩個變量的內存是連續的,請使用struct

0

它的工作原理是因爲你的編譯器以ab的方式分配了內存,b緊跟在a之後。這是不可重現的,這就是爲什麼你有未定義的行爲

只需在ab之間插入另一個變量,使用其他編譯器或(我最喜歡的:)重命名變量。我見過一個按字母順序排列變量的編譯器。

您的代碼意外「有效」。

0

這是一個未定義的行爲,所以它通常不起作用。一個不好的例子是clang。這個編譯器足夠聰明,可以在啓用鏈接時優化時優化b