2012-02-19 32 views
0

我有這樣的代碼在C++中即給予怪異輸出:這段代碼爲什麼表現怪異?

#include<iostream> 
using namespace std; 
int main(){ 
    int r[15]={0}; 
    int n = 5; 
    r[15]=20; 
    cout<<n;  
} 

輸出顯然應5,但它給了我20.現在我知道[R [15]是出界。這段代碼應該拋出一個例外,試圖訪問r [15],不應該嗎?但是,它通常用g ++編譯並給出錯誤的輸出。我無法弄清楚是什麼導致了這種異常。誰能幫忙?

僅供參考,這個代碼僅僅是一個樣品,我不得不從我花了很多它,否則,可能會一直,如果一個異常被拋出保存時間較大的代碼輸出圖這個bug。

更新: 我檢查了下面的代碼:

#include<iostream> 
using namespace std; 
int main(){ 
    int n = 5; 
    int r[15]={0}; 
    r[15]=20; 
    cout<<n; 
} 

Output: 
20 

我檢查了下面的代碼太:

#include<iostream> 
using namespace std; 
int main(){ 
    int n = 5; 
    int a=5; 
    int r[15]={0}; 
    r[15]=20; 
    cout<<n<<endl<<a; 
} 

Output: 
5 
5 

因此,如果堆棧的解釋是正確的,無論是價值觀應該」在這種情況下也經過了修改,對吧?它沒有。

+0

尤其是當你學習,可以考慮使用'的std ::矢量'和'在()' - 更容易安全使用和'在()如果給定的索引無效'會拋出異常。 – 2012-02-20 08:15:18

回答

9

由於r是一個15元件陣列,r[14]是最後一個元素。因此r[15]=20;是未定義的行爲。 C++不會執行邊界檢查,因此在處理純數組時不會收到異常。

在你的情況下r[15]=20恰好覆蓋了存儲n的精確位置的堆棧。

+0

檢查我的更新。 – 2012-02-19 13:12:48

+2

@dpacmittal未定義的行爲。再仔細閱讀我的答案*。 「它發生**覆蓋」。沒有保證,編譯器可以並將重新排序。跟我說:*未定義的行爲*。 – cnicutar 2012-02-19 13:14:18

+0

啊,謝謝。這很有道理:) – 2012-02-19 13:21:23

5

現在我知道r[15]是超出界限。此代碼應該拋出一個例外,試圖訪問r[15],不是嗎?

除非你正在使用某種形式的檢查庫,沒有的。 C(和C++)是非常接近機器,所以你可以讓自己處於這種情況。 (這是他們的權力的一部分。)還有一些編譯器會插入邊界檢查(在運行時的成本)編譯器標誌,但gcc不這樣做(你可以找到補丁集將其添加爲一個功能,但我認爲只對於C)。

發生了什麼事那裏(顯然)是你的n變量r陣列的15個插槽後立即結束在堆棧上:

+-------+ 
| r[0] | 
| r[1] | 
| r[2] | 
... 
| r[13] | 
| r[14] | 
| n  | 
+-------+

...等書面形式向您出界外進入r[15]最終覆蓋它(你的具體情況,這不是問題,你可以或應該指望,對事物的堆棧上的順序不被定義爲在其源要聲明的順序來確定,並且可以井不是是)。

+0

我不確定你的解釋是否正確,因爲即使我在r之前聲明n,問題依然存在。另外,如果我引入一個新的變量'a',問題就會消失。我會更新我的問題幷包含新代碼。 – 2012-02-19 13:08:54

+1

@dpacmittal:這裏的意思是分配給'r [15]'會導致怪異的行爲。它出界了,所以不要這樣做。 :-)你得到的精確怪異行爲將取決於編譯器(至少),並且很可能取決於運行時環境。請參閱答案中的最後一句,特別是位* *「在您的特定情況下; **這不是您可以或應該依賴的行爲**」*。 – 2012-02-19 13:18:51

+0

是的,我現在明白了。謝謝 :) – 2012-02-19 13:20:50