![](/img/trans.png)
[英]typecasting unsigned char and signed char to int in 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。
當從char
為int
時,值仍為-1,但它是32位表示形式,二進制形式為11111111 11111111 11111111 11111111
或十六進制0xffffffff
當將其解釋為無符號整數時,顯然會保留所有位,因為長度相同,但是現在將其作為無符號數量處理。
0xffffffff = 4294967295 (unsigned)
0xffffffff = -1 (signed)
C中有三種字符類型, char
, signed char
和unsigned char
。 純char
與帶signed char
或unsigned char
具有相同的表示形式; 選擇是實現定義的。 似乎在您的實現中簽名了純char
。
所有這三種類型具有相同的尺寸,這可能是8位( CHAR_BIT
,在定義<limits.h>
,指定一個字節的比特數)。 我假設8位。
char c=0xff;
假設對普通char
進行了簽名,則值0xff
( 255
)在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.