[英]why char a=-1 is different from unsigned char b=-1, in C programming
我在下面寫了一個小程序。
#include <stdio.h>
main(){
char a=-1;
unsigned char b=-1;
printf("%d %d\n",a,b);
printf("%x %x\n",a,b);
if(a==b) printf("equal\n");
else printf("not equal\n");
}
該編的輸出為:
-1 255
ffffffff ff
not equal
由於char僅為一個字節,並且-1以2的補碼形式表示,我認為0xff將同時存儲在a和b中,因此兩者應相等。 誰能告訴我為什么它們不同以及為什么a的十六進制表示是0xffffffff而不是0xff。 我有一個相關的鏈接http://embeddedgurus.com/stack-overflow/2009/08/a-tutorial-on-signed-and-unsigned-integers/,但我找不到答案。 任何幫助將不勝感激。 謝謝。
他們是一樣的。 或者,它們的基本表示形式是相同的(假設您的編譯器使用兩個補碼形式)。
另一方面,它們表示的值為-1和255。
當您打印它們時,它們將擴展為int
數據類型。 unsigned char
是零擴展的,而signed char是符號擴展的,這說明了您看到的差異。
比較兩個值時,會發生相同的擴展名。 a == b
不比較基礎表示,而是將兩個值都擴展為int
因此將255與-1比較,這是不相等的。
請注意,普通char
可以是有符號的也可以是無符號的。 在您的環境中,顯然已簽名。
char
類型是一種異常,因為它與有signed char
或unsigned char
不同(不同於其他整數類型short
, int
, long
等-除非明確聲明為unsigned
否則它們是隱式unsigned
)。 char
是否實際簽名取決於實現,並且某些編譯器甚至允許您通過命令行開關指定簽名。
底線:永遠不要假設char
是帶符號的或無符號的-如果您實際上需要帶符號的或無符號的8位數字,則顯式使用帶signed char
或unsigned char
,或者更好的是,使用<stdint.h>
int8_t
或uint8_t
。
一個signed int
簽訂后,一個unsigned int
是無符號。 如果僅使用int
,則表示signed int
。 short
, long
或long long
也是如此。 但是,對於char
並非如此。 一個signed char
是簽名的,一個unsigned char
是未簽名的,但是只有char
可以是簽名的也可以是未簽名的。 數據類型char應該包含一個“字符”,也就是這個名稱,因此它不是“真正”一個整數類型來保存要在計算中使用的整數。 當然,字符實際上是某種整數,但是哪種類型取決於實現(C標准不強制使用任何特定的類型)。 因此,如果要將char類型用於整數值(也在計算中使用),請始終明確使用有signed char
或unsigned char
並且僅在真正處理字符或對代碼絕對沒有區別時才使用char
字符已簽名或未簽名。
因為你實現定義比較失敗char
是其實signed char
,讓您比較一個signed char
到一個unsigned char
在最終if
語句。 每當您比較兩個不同類型的整數時,編譯器都會在實際執行比較之前根據C標准的規則將兩個值轉換為相同類型。 在您的情況下,這意味着C編譯器實際上會執行以下操作:
if((int)a==(int)b) printf("equal\n");
else printf("not equal\n");
}
現在很明顯,為什么這兩個值不匹配。 (int)a
的值為-1
,但是(int)b
的值為255
,並且這兩個值不相等。
根據類型提升的規則, char
(在您的情況下為signed)將提升為int
而unsigned char
也將提升為int
。 ISO C 2011標准說:
如果一個int可以表示原始類型的所有值(受位字段的寬度限制),則該值將轉換為int; 否則,它將轉換為unsigned int。 這些稱為整數促銷。)所有其他類型均不受整數促銷的影響。
整數促銷保留包括符號在內的價值。 如前所述,是否將“普通”字符視為已簽名是實現定義的。
盡管在普通的“字符”周圍存在一些歧義(請參見默認情況下,字符是有符號的還是無符號的? ),但我認為這並不是唯一的事情。
文字-1是整數,不會(為了參數而將sizeof(int)> sizeof(char))“適合”到char中。兩個補碼的位模式0xffff(為參數而為32位int)為被截斷並復制到此處。
當您調用printf()時,參數將提升為整數類型,帶符號類型為“符號擴展”,但不帶符號的“ b”則為零,且填充為零。 當您將“ ==”與兩個不同的類型一起使用時,將執行類似(但不一定相同)的類型轉換(也稱為“通常的算術轉換”)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.