2011-08-26 70 views
0
int test[3] = {1,2,3}; 
cout<<test[3]<<endl;  
// this will get a error 

指針數組問題

int test[3] = {1,2,3}; 
int (*A)[3]; 
A = &test; 
cout<<test[3]<<(*A)[3]<<endl; 
// this will print -858993460 withiout any errors 

所以任何人都可以告訴我爲什麼?我真的很困惑。

在第一種情況下,爲什麼它不是出現跨界錯誤,而是一個未定義的錯誤? 以及爲什麼第二種情況不會出錯?我曾經認爲他們是相同的...

其實我確實知道數組從0開始,我很困惑,爲什麼第一個得到一個錯誤,但第二個不會?

+0

您指的是數組中的第4個位置而不是第3個位置。您應該打印測試[2]以獲得值'3'。 – jmnwong

+0

請注意,在C++中,數組是基於0的。 – ereOn

回答

3

未定義的行爲似乎是新手理解的一個非常棘手的概念。但是非常簡單,如果你打破C++的規則(因爲這兩個你的例子),那麼很多時候,你的程序的行爲是不確定的。這意味着它說的是什麼,並且它沒有任何問題,問'爲什麼這樣做',因爲不再有適用於您的情況的任何規則或法律。

+0

如果我正在編寫C++編譯器,我會非常想要引起某些常見的未定義行爲(如寫入緩衝區末尾)做一些象刪除操作系統這樣的表達式。這將鼓勵謹慎編程。 – Daniel

+0

有人應該編寫一個用於教學的編譯器,它在未定義的行爲上可靠地失敗。這就像騎自行車和穩定器一樣。 – john

+0

這就是所謂的Java – Daniel

10

您正在調用未定義的行爲。在這兩種情況下,您都在索引數組的範圍之外;相應的行爲是未定義的。它可能會崩潰,或者它可能會輸出廢話,或者它可能會做其他事情。

+2

+1。所以要簡短一點:**永遠不要再這樣做了!** :) – ereOn

2

C中的數組索引/ C++從0。因此尺寸3的陣列開始,具有有效的索引0,1和2

現在,你有程序棧上的可變test。因此,數組邊界外的內存仍然是你的(這就是爲什麼當你正在讀取數組的索引3時,你沒有得到分段錯誤(訪問衝突)錯誤)。但是,您正在讀取以前函數調用中的亂碼,內存中的常駐亂碼或函數中的其他變量的部分堆棧。這就是爲什麼你得到奇怪的數字。

你應該小心走出數組邊界。在一個複雜的程序中,這實際上很難調試,因爲您在堆棧上更改其他變量,並且在調試時您看到的所有變量都是您甚至沒有碰到的變量中的隨機行爲!