2015-05-08 43 views
0

我正在閱讀的一本c編程書(c編程,現代方法第2版)說,當在無符號整數運算期間發生溢出時,結果是定義「。爲什麼整數在溢出時有不同的行爲

這裏是一個小的代碼示例

#include <stdio.h> 

int main() 
{ 
    unsigned short int x = 65535; // The unsigned short int is at the maximum possible range 
    x += 1; // If I add one to it will overflow. 
    printf("%u", x); // the output will be zero or one if decide to add plus one again to x 
    return 0; 
} 

他接着說,「爲有符號整數,這些整數的行爲沒有定義」。這意味着程序可以打印出錯誤的結果,也可能導致程序崩潰。

這是爲什麼?

+1

你問爲什麼有符號整數溢出的行爲是未定義的,(*因爲語言規範說它是*),或爲什麼規範定義無符號整數溢出但聲明有符號整數溢出未定義(* [簽署的值](http://stackoverflow.com/questions/18195715/why-is-unsigned-integer-overflow-defined-behavior-but-signed-integer-overflow-is)*)?另外,請不要使用'%d'打印無符號值 - 出於某種原因,'%u'存在。 –

+0

@IskarJarak「爲什麼規範定義了無符號整數溢出,但聲明瞭有符號整數溢出未定義?」你的這句話是我問的。 –

+0

@LuisAverhoff然後看到重複的鏈接。這已經被問過。 –

回答

3

它涉及到硬件表示,並且有多種方法來表示二進制符號整數類型(符號幅度,補碼,二進制補碼)以及對它們的操作。當發生溢出時(例如,觸發硬件陷阱,使用模數等),這些具有完全不同的含義。

所有以二進制表示無符號整型值並在這些值上實現數值運算的明顯方法都具有相同的結果 - 本質上,硬件中的數值運算使用模運算。

對於基本類型(以及其他事物),當存在多種可行的實現方式時,標準通常允許編譯器供應商自由,而這些選項具有不同的後果。有多種簽名整數類型的方法,以及使用每種方法的現實世界的硬件。它們足夠不同以保證行爲沒有定義(因爲該術語在標準中定義)。

+0

這個答案完全正確。另外值得一提的是,不幸的是,因爲該標準表明行爲沒有定義,所以編譯器供應商可以做任何事情*。通過在C中添加來溢出一個帶符號的int不一定要做你的CPU的ADD指令在溢出時所做的。已知優化器利用這種不確定性並完全優化加法。國際海事組織這是一個危險的遊戲玩規格。 – StilesCrisis

+0

是的。我會考慮這個問題,但我首先想到的是,考慮到原來的問題,這有點遠。你所描述的是一種自我實現的預言,有時與未定義的行爲相關聯(由於存在一系列現實世界的行爲,標準中沒有定義標準,因爲它沒有定義,實施者選擇支持更多可能的行爲)。然而,這是一些未定義的結果,而不是它首先未定義的原因。 – Peter

+0

對我來說,「不確定是因爲不同的CPU有不同的行爲」這個明顯的推論是「C編譯器會遵循我的CPU架構的行爲」,但實際情況要微妙得多。這是一個陷阱。 – StilesCrisis