簡體   English   中英

從帶符號的char到int類型的C類型轉換

[英]C typecasting from a signed char to int type

在下面的代碼段中,輸出不應該為1嗎? 為什么我得到的輸出為-1和4294967295? 我了解的是變量c,這里是帶符號的類型,所以它的值不應該為1嗎?

char c=0xff;
printf("%d %u",c,c);

c是帶符號的類型。 一個字符是8位。 因此,您有一個8位帶符號的數量,所有的位均為1。在二進制補碼機上,其值為-1。

當您執行此類操作時,某些編譯器會警告您。 如果您使用的是gcc / clang,請打開所有警告。

腳注:在某些機器上,如果編譯器將'char'視為無符號,則其值可能為255。

您得到正確的答案。

%u格式說明符指示該值將為unsigned int 編譯器會自動將8位char提升為32位int 但是,您必須記住, char是帶符號的類型。 因此,值0xff實際上為-1。

當從charint時,值仍為-1,但它是32位表示形式,二進制形式為11111111 11111111 11111111 11111111或十六進制0xffffffff

當將其解釋為無符號整數時,顯然會保留所有位,因為長度相同,但是現在將其作為無符號數量處理。

0xffffffff = 4294967295 (unsigned)
0xffffffff = -1 (signed)

C中有三種字符類型, charsigned charunsigned char char與帶signed charunsigned char具有相同的表示形式; 選擇是實現定義的。 似乎在您的實現中簽名了純char

所有這三種類型具有相同的尺寸,這可能是8位( CHAR_BIT ,在定義<limits.h> ,指定一個字節的比特數)。 我假設8位。

char c=0xff;

假設對普通char進行了簽名,則值0xff255 )在char類型的范圍之外。 由於您不能將值255存儲在char對象中,因此將隱式轉換該值。 此轉換的結果是實現定義的,但很可能是-1

請牢記這一點: 0xff只是編寫255另一種方式,而0xff-1是兩個不同的值。 不能將值255存儲在char對象中。 它的值為-1 整數常量(無論是十進制,十六進制還是八進制)都指定值,而不是表示形式。

如果您確實想要一個值為0xff的單字節對象,請將其定義為unsigned char ,而不是char

printf("%d %u",c,c);

當將小於int的整數類型的值傳遞給printf (或任何可變參數函數)時,如果該類型可以容納該類型的整個值范圍,則將其提升為int ,否則將提升為unsigned int 對於char類型,幾乎可以肯定將其提升為int 因此,此調用等效於:

printf("%d %u", -1, -1);

"%d"格式的輸出是顯而易見的。 "%u"的輸出不太明顯。 "%u"告訴printf ,相應的參數的類型為unsigned int ,但是您已將其傳遞為int類型的值。 什么可能發生的是,的表示int值被視為好像它是類型unsigned int ,最有可能產生UINT_MAX ,這恰好是4294967295您的系統上。 如果確實要這樣做,則應轉換unsigned int類型。 這個:

printf("%d %u", -1, (unsigned int)-1);

定義明確。

您的兩行代碼正在玩各種類型的游戲,將一種類型的值視為另一種類型,並進行隱式轉換,這些轉換可能產生實現定義的結果和/或取決於編譯器的選擇。碰巧使。

無論您要做什么,毫無疑問,這是一種更干凈的方法(除非您只是嘗試查看實現如何使用此特定代碼)。

讓我們從使用OP的“ c,這里是帶符號類型”的假設開始

char c=0xff;  // Implementation defined behavior.

0xff是一個十六進制常數 ,值為255,類型為int

...新類型已簽名,並且值不能在其中表示; 結果是實現定義的,還是引發實現定義的信號。 §6.3.1.43

因此, c的值就是實現定義的(ID)。 讓我們假設8位回繞的通用ID行為,即c > -1。


已簽名的char將作為printf("%d %u",c,c);的可變參數的一部分提升為int printf("%d %u",c,c); printf("%d %u",-1, -1); "%d"打印-1沒問題,並且打印"-1"

"%x"打印一個int -1是未定義的行為(UB),因為它是不匹配的說明符/類型,並且不屬於可以在兩種類型中表示的情況。 普通的UB將打印該值,就像在傳遞該值之前將其轉換為unsigned一樣。 UINT_MAX == 4294967295 (4字節)時,將值打印為-1 + (UINT_MAX + 1)或“ 4294967295”。


因此,使用ID和UB,您可以得到結果,但是健壯的代碼將被重寫為兩者都不依賴。

暫無
暫無

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

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