2014-05-23 31 views
30

據我瞭解,應該給你一個溢出錯誤,當我把它寫這樣的:爲什麼int.MaxValue - int.MinValue = -1?

public static void Main() 
{ 

    Console.WriteLine(int.MaxValue - int.MinValue); 
} 

它正確地給我一個溢出錯誤。

但是:

public static void Main() 
{ 

    Console.WriteLine(test()); 
} 

public static Int32 test(int minimum = int.MinValue, int maximum = int.MaxValue) 
{ 
    return maximum - minimum; 
} 

將輸出-1 它爲什麼要這樣做呢?它應該拋出一個錯誤,因爲它顯然是一個溢出!

+6

難道我是被教會2147483647的唯一的人 - ( - ?2147483648)實際上是4294967295 – Aelphaeis

+0

是4294967295並不是一個int – harold

+0

你會期望2147483647 - 2147483648給你什麼? –

回答

46

int.MaxValue - int.MinValue = int不能容納的值。因此,數字回到-1。

它像2147483647 - ( - 2147483648)= 4294967295這不是這個恆定的int

Int32.MinValue Field

2,147,483,648;即十六進制 0x80000000。

而且Int32.MaxValue Field

的這個恆定值是2147483647;即十六進制 0x7FFFFFFF。

MSDN

當整數溢出時,會發生什麼取決於執行 背景下,可以選中或取消選中。在選中的上下文中,會引發OverflowException。在未檢查的上下文中,結果的最高位將被丟棄並繼續執行。因此,C#讓您選擇處理或忽略溢出。

+4

編輯解釋它,我發現它驚奇的是默認情況下編譯器處於未選中狀態。 – Aelphaeis

+0

@Aelphaeis: - 是的,並添加到它檢查的關鍵字用於顯式啓用整型算術運算和轉換的溢出檢查。 –

+2

@Aelphaeis我很驚訝以及我確定默認被檢查。但[每MSDN,確實'/ checked-'是默認](http://msdn.microsoft.com/en-us/library/h25wtyxf.aspx)。這似乎是一個糟糕的默認選擇,因爲它允許編程錯誤在運行時被忽略(並且可能具有[安全影響?](http://cwe.mitre.org/data/definitions/190.html))。我想知道爲什麼C#團隊做出了這樣的選擇...... – LB2

13

這是因爲編譯時溢出檢查你的代碼。該生產線

Console.WriteLine(int.MaxValue - int.MinValue); 

實際上不會在運行時錯誤,它會簡單的寫「-1」,但由於溢出檢查你的編譯錯誤「操作在檢查模式下編譯時溢出」。

要解決的編譯時溢出在這種情況下檢查,你可以這樣做:

  unchecked 
     { 
      Console.WriteLine(int.MaxValue - int.MinValue);     
     } 

這將運行良好,輸出「-1」

+0

大喊@邁克爾突出顯示瞭如何運行時溢出檢查在編譯級別的選項。 – Aidanapword

+1

爲了完成這個答案,你也可以顯示相反的效果 - 在''test'方法中將'checked'放在計算中 - 使得那個拋出異常,這是OP想要的。 – ClickRick

2

默認的項目級別設置控制此默認設置爲「未選中」。轉到項目屬性「生成」選項卡,「高級」按鈕,可以打開溢出檢查。彈出窗口允許您打開溢出檢查。您鏈接到的.NET Fiddle工具似乎執行了一些額外的靜態分析,這會阻止您看到真實的即時運行時行爲。(上面第一個代碼片段的錯誤是「操作在編譯時在檢查模式下溢出」。你沒有看到運行時錯誤。)

2

我認爲它比溢出更進一步。

,如果我看這個

Int64 max = Int32.MaxValue; 
Console.WriteLine(max.ToString("X16")); // 000000007FFFFFFF 
Int64 min = Int32.MinValue; 
Console.WriteLine(min.ToString("X")); //FFFFFFFF80000000 
Int64 subtract = max - min; 
Console.WriteLine(subtract.ToString("X16")); //00000000FFFFFFFF <- not an overflow since it's a 64 bit number 
Int32 neg = -1 
Console.WriteLine(neg.ToString("X")); //FFFFFFFF 

這裏可以看到,如果你只是減去2的補十六進制值),你得到的是-1的32位數目。 (trunkating領先0的

2的補碼運算後可以很有趣http://en.wikipedia.org/wiki/Two「s_complement