2012-01-28 302 views
29

INT之間的真正區別:「Int」和「無符號整型」

32位int數據類型可以在 -2147483648範圍保持整數值到2,147,483,647。您也可以將這種數據類型 稱爲signed int或signed。

無符號整型

的32位無符號int數據 類型可在0範圍內的保持整數值到4294967295。你也可以將這種數據類型簡稱爲無符號。

好的,但是,在實踐中:

int x = 0xFFFFFFFF; 
unsigned int y = 0xFFFFFFFF; 
printf("%d, %d, %u, %u", x, y, x, y); 
// -1, -1, 4294967295, 4294967295 

沒有區別,O.o.我有點困惑。

+1

您需要考慮'int'和'unsigned int'的_binary_表示。 – Oded 2012-01-28 13:08:54

+1

這可能發生的真正原因是C是* weakly * * typed *語言。但'unsigned int'和'int'確實不同。 – cha0site 2012-01-28 13:13:55

+1

http://stackoverflow.com/questions/247873/signed-versus-unsigned-integers – 2012-01-28 13:18:09

回答

34

呵呵。你有一個隱含的演員,因爲你告訴printf什麼類型的期望。

嘗試此關於大小,而不是:

unsigned int x = 0xFFFFFFFF; 
int y = 0xFFFFFFFF; 

if (x < 0) 
    printf("one\n"); 
else 
    printf("two\n"); 
if (y < 0) 
    printf("three\n"); 
else 
    printf("four\n"); 
21

是的,因爲在你的情況下,他們使用the same representation

位模式0xFFFFFFFF恰好在解釋爲32b有符號整數時看起來像-1,而在解釋爲32b無符號整數時看起來像4294967295。

char c = 65相同。如果你把它解釋爲一個有符號的整數,那它就是65.如果你把它解釋爲一個字符,它就是a


正如R和pmg指出的那樣,從技術上講,它是未定義的行爲來傳遞與格式說明符不匹配的參數。所以程序可以做任何事情(從打印隨機值到崩潰,打印「正確」的東西等)。

標準分出來的7.19.6.1-9

如果轉換SPECI網絡陽離子是無效的,行爲是理解過程定義網絡。 如果 對於相應的轉換 規範,任何參數都不是正確的類型,則行爲是不確定的。

+4

真正的原因是他使用%u來打印兩者。 – 2012-01-28 13:11:10

+3

真正的原因是他**通過將非類型匹配的格式字符串傳遞給'printf'來調用未定義的行爲**。我幾乎想要對所有跳過這個的答案進行倒推,並指出與表示無關的東西... – 2012-01-28 13:33:07

+1

@R ..沒錯,格式和參數不匹配是未定義的行爲。隨時downvote,我不會介意:-) – cnicutar 2012-01-28 13:33:55

1

該類型只是告訴你位模式應該表示什麼。這些位只是你所做的。相同的序列可以用不同的方式解釋。

1

printf函數解釋了您根據匹配位置中的格式說明符傳遞的值。如果您告訴printf您通過了int,但是通過unsignedprintf會將其中一個重新解釋爲另一個,並打印您看到的結果。

3

intunsigned int的內部表示是相同的。

因此,當您將相同的格式字符串傳遞到printf時,它將被打印爲相同。

但是,當您比較它們時存在差異。 考慮:

int x = 0x7FFFFFFF; 
int y = 0xFFFFFFFF; 
x < y // false 
x > y // true 
(unsigned int) x < (unsigned int y) // true 
(unsigned int) x > (unsigned int y) // false 

這也可以是一個警告,因爲當比較有符號和無符號整數其中一人將被隱式鑄造相匹配的類型。

7

問題是你調用了Undefined Behaviour


當你調用UB任何事情都有可能發生。

作業沒問題;有在第一線的隱式轉換

int x = 0xFFFFFFFF; 
unsigned int y = 0xFFFFFFFF; 

然而,調用printf,是不正常

printf("%d, %d, %u, %u", x, y, x, y); 

它是UB的失配的%說明符和參數的類型。
在你的情況,你通過指定順序2 int秒和2個unsigned int小號提供1 int,1 unsigned int,1 int和1 unsigned int


不要做UB

+0

-1,錯誤。這不是未定義的行爲。查看C99第6.5.2.2節第6段。 – cha0site 2012-01-28 13:47:13

+1

@ cha0site:我具體地說,作業沒問題:*第6.5.2.2節第6段*並不適用於我的答案。 UB在'printf'調用中:check [7.19.6.1](http://port70.net/~nsz/c/c99/n1256.html#7.19.6):「如果任何參數不是正確的類型對於相應的轉換規範,行爲是未定義的「。另外請注意'printf'是一個函數,其參數數量可變,根據原型進行轉換是不可能的。 – pmg 2012-01-28 13:55:48

+0

C99 [6.5.2.2](http://port70.net/~nsz/c/c99/n1256.html#6.5.2.2)優先於此。正在進行整數升級。我可能誤解了 - 可能是第5段。 – cha0site 2012-01-28 14:00:05

1

他在詢問的區別。 當你在談論不確定的行爲你是對語言規範提供擔保的水平 - 這是遠離現實。 要了解真正的區別請這個片段(當然這是UB但它是你最喜歡的編譯器的完美定義):

#include <stdio.h> 

int main() 
{ 
    int i1 = ~0; 
    int i2 = i1 >> 1; 
    unsigned u1 = ~0; 
    unsigned u2 = u1 >> 1; 
    printf("int   : %X -> %X\n", i1, i2); 
    printf("unsigned int: %X -> %X\n", u1, u2); 
} 
9

有一個在他們是如何存儲在存儲器和寄存器兩者之間沒有區別,沒有簽名和未簽名的int寄存器版本,沒有與int一起存儲的簽名信息,差異只在執行數學運算時變得相關,數學運算的簽名和未簽名版本嵌入到CPU中,簽名告訴編譯器使用哪個版本。

+0

這個答案是最簡單的 – 2016-06-17 20:37:41

1

這是一個非常簡單的例子。二進制表示是它被提及但從未顯示的關鍵。 如果0XFFFFFFF =機器碼= 1111 1111 1111 1111 1111 1111 1111 1111 = 4,294,967,295數字的正數表示,則以十六進制形式無符號數。 這是一切都很好,但我們需要一種方法來表示負數。因此,大腦決定二補。 這是什麼意思,簡而言之,他們佔據了最左邊的數字,並決定當它是1時(隨後是全部1,直到到達最左邊的位),如果數字爲0,則該數字爲負,這是正數。 現在讓我們來看看會發生什麼0000 0000 0000 0000 0000 0000 0000 0011 = 3。 現在讓我們繼續添加到這個數字 0111 1111 1111 1111 1111 1111 1111 1111 = 2,147,483,645 帶符號整數的最高正數。 讓我們加1(這裏你可能想查看二進制加法) 我們必須一直帶着這個。 1111 1111 1111 1111 1111 1111 1111 1110 = -1 所以我想在很短,我們可以說,不同的是一個允許負數其他沒有,這是由於符號位或最左邊的位或最重要的位。

相關問題