簡體   English   中英

為什么在C編程中char a = -1與無符號char b = -1不同

[英]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 charunsigned char不同(不同於其他整數類型shortintlong等-除非明確聲明為unsigned否則它們是隱式unsigned )。 char是否實際簽名取決於實現,並且某些編譯器甚至允許您通過命令行開關指定簽名。

底線:永遠不要假設char是帶符號的或無符號的-如果您實際上需要帶符號的或無符號的8位數字,則顯式使用帶signed charunsigned char ,或者更好的是,使用<stdint.h> int8_tuint8_t

一個signed int簽訂后,一個unsigned int是無符號。 如果僅使用int ,則表示signed int shortlonglong long也是如此。 但是,對於char並非如此。 一個signed char是簽名的,一個unsigned char是未簽名的,但是只有char可以是簽名的也可以是未簽名的。 數據類型char應該包含一個“字符”,也就是這個名稱,因此它不是“真正”一個整數類型來保存要在計算中使用的整數。 當然,字符實際上是某種整數,但是哪種類型取決於實現(C標准不強制使用任何特定的類型)。 因此,如果要將char類型用於整數值(也在計算中使用),請始終明確使用有signed charunsigned 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)將提升為intunsigned char也將提升為int ISO C 2011標准說:

如果一個int可以表示原始類型的所有值(受位字段的寬度限制),則該值將轉換為int; 否則,它將轉換為unsigned int。 這些稱為整數促銷。)所有其他類型均不受整數促銷的影響。

整數促銷保留包括符號在內的價值。 如前所述,是否將“普通”字符視為已簽名是實現定義的。

盡管在普通的“字符”周圍存在一些歧義(請參見默認情況下,字符是有符號的還是無符號的? ),但我認為這並不是唯一的事情。

文字-1是整數,不會(為了參數而將sizeof(int)> sizeof(char))“適合”到char中。兩個補碼的位模式0xffff(為參數而為32位int)為被截斷並復制到此處。

當您調用printf()時,參數將提升為整數類型,帶符號類型為“符號擴展”,但不帶符號的“ b”則為零,且填充為零。 當您將“ ==”與兩個不同的類型一起使用時,將執行類似(但不一定相同)的類型轉換(也稱為“通常的算術轉換”)。

另請參見C函數調用Signed和Unsigned中的 默認參數提升 ,以及C中的位擴展如何工作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM