2017-07-31 64 views
0
#include <stdio.h> 
int main() 
{ char i=0;    
    for(;i>=0;i++);  
    printf("%d",i);  
    return 0; 
} 

該程序的輸出是-128。據我瞭解,字符變量會溢出,所有位將爲0.並且取二進制補碼將再次爲0.有人可以解釋這個過程嗎?這個程序的輸出是怎樣的?

編輯:只是爲了澄清,這不是我的程序。這是一場競爭性考試中的編程問題。

+2

您可能有*未定義的行爲*。溢出有符號整數變量會導致UB。 'char'可以是'signed'或'unsigned'。 –

+1

首先,您應該修復代碼。這是標記C和代碼顯然是C除了包含和命名空間的東西,這不屬於這裏。 (把#include '代替) –

+2

如果你可以完全按照你的問題所示編譯代碼,那麼你使用的是C++編譯器。用C++編譯器編譯C代碼是一個壞主意。 –

回答

5

您對溢出的假設是不正確的。溢出無符號類型將所有位設置爲零,但溢出有符號類型爲未定義,所以它可能會導致任何值。

你得到的結果是什麼,因此要看你的(編譯器)實現。如果

  • 你實現了簽署char這可能解釋。
  • A char有8位。
  • 負數用2的補碼錶示。
  • 溢出帶符號的值會造成環繞。 (這是使用2的補數的簡單實現的結果,見下文)

鑑於所有這些假設(請記住,這些沒有僅由C指定),遞增127以最大可能char值(表示爲0111 1111)產生-128,最小可能值(表示爲1000 0000)。

TL; DR - 你的代碼是不確定的,不寫這樣的代碼。

0

由於你的char被簽名,它可以在-128到127之間(8位),並且你正在遞增,直到達到最大值,然後溢出併成爲 - 值,因爲這就是寫入負值的方式以位爲單位。 看看下面的圖片:

enter image description here

附:在循環內部進行一些打印,你也可以自己弄清楚。

+0

這張照片起初看起來很不錯,但它實際上非常具有誤導性,因爲它呈現了非常不同的「多餘的128」表示,*不是* 2的補充。 –

+0

我沒有看着它只是試圖給出具有8位數字表示的圖形表示。我想新圖像有更好的解釋,但在一個較小的樣本。感謝您指出了這一點。 – milorads

+0

感謝您的修復。像這樣的圖片很棒 - 只要它們準確無誤! –

0

實際上在每次迭代中,循環將增加i,1,這導致我們到i = 127

  • 現在,讓我們看看它的二進制表示0111-1111
  • 現在,如果我們增加1。然後
  • 0111-1111 + 0000-0001 = 1000-0000
  • 現在,分析這一點,MSB設置,這意味着它是一個負數
  • 負數是另存爲2的補
  • 2的的1000-0000補= -127
  • 因此循環中斷

希望你能得到它。

+0

雖然這很可能是發生了什麼,但它需要所有*不保證的假設*我已在我的答案中列出。我不認爲這是一個好主意,寫一個答案,看起來這實際上是* defined *行爲。 –