2013-08-29 54 views
3

我工作的一個C的輸出問題:期待SIGSEGV,但得到正常工作

#include<stdio.h> 
int main() 
{ 
    int a[][2][3]={0,1,2,3,4,5,6,7,8,9,10,11,12}; 
    int i=-1; 
    int d; 
    d=a[i++][++i][++i]; 
    printf("%d\n",d); 
    return 0; 
} 

鏈接Ideone:http://ideone.com/1oS9Un

,並期待一個運行時錯誤,但令人驚訝的代碼上工作正常CodeBlocks,Dev C++和Ideone。根據我的說法,每個存儲器地址在運行時由以下等式通過編譯器解析:a [i] [j] [k] = (*(a + i)+ j)+ k)每個編譯器應首先解析內部括號,然後解析下一個內部括號等。

因此在給定行

d=a[i++][++i][++i]; 

應被解析爲:

d=*(*(*(a+i++)+ ++i)+ ++i) 

也通過,http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm (請參閱注2)

最內的括號應首先解決,它的值應該是a-1,而我變成0.因此,我們應該得到一個SIGSEGV錯誤,因爲我們試圖訪問內存而不是特定的由編譯器標記的盟友仍在所有三個編譯器中顯示輸出。請解釋一下。

+2

未定義......... – devnull

回答

3

因此,我們應該得到一個SIGSEGV錯誤

不,我們不應該。如果行爲是undefined,則可能發生任何事情。不存在段錯誤的保證。

P.S.你的代碼的行爲是不確定的,但是除了問題中陳述的原因以外。實際的原因是您在序列點之間多次修改i。請參閱C FAQ

+0

但爲什麼這種未定義的行爲? –

+1

@DrefD:http://c-faq.com/expr/index.html – NPE

0

沒有任何C標準規定「如果超出數組範圍,那麼系統必須在運行時使用分段錯誤(又稱內存訪問衝突)終止進程」。

C是不安全從這個意義上說。你可以自由地編寫錯誤的代碼,這些代碼可能有時會起作用,而在其他情況下會失敗,因爲它是錯誤的。這個標準並不打算定義你出錯時應該發生什麼 - 它意在定義什麼是正確的,當事情是正確的時候會發生什麼,並且(通常暗示)什麼是錯誤,但是(再次)不是當事情出錯時會發生什麼。這會對實現增加額外的(並且可以說是非常不必要的)約束。

這就是爲什麼我們有術語未定義的行爲,我相信這是爲C標準創造的。 「未定義」是當你做某件未被覆蓋的事情時發生的事情 - 有時候它可能仍然是一個合乎邏輯的結果,只是你不能保證它是一致的。

相關問題