[英]Sign extension query in case of short
鑒於
unsigned short y = 0xFFFF;
當我打印時
printf("%x", y);
我得到: 0xFFFF;
但是當我打印
printf("%x", (signed short)y);
我得到: 0xFFFFFFFF
整個程序如下:
#include <stdio.h>
int main() {
unsigned short y = 0xFFFF;
unsigned short z = 0x7FFF;
printf("%x %x\n", y,z);
printf("%x %x", (signed short)y, (signed short)z);
return 0;
}
當我們將類型轉換為低字節到高字節數據時,會發生符號擴展,但是這里我們將類型轉換為從短到帶符號的short。 在這兩種情況下,sizeof((signed short)y)或sizeof((signed short)z)均輸出2個字節。 如果符號位為零(如0x7fff),則剩余2個字節。 很感謝任何形式的幫助!
第一個printf
輸出符合預期。 第二個printf
產生未定義的行為。
在C語言中,當您將一個小於int
值傳遞給可變參數時,該值總是隱式轉換為int
類型。 在物理上不可能傳遞short
或char
可變參數。 隱式轉換為int
是您的“符號擴展”發生的地方。
因此,您的printf("%x", y);
等價於printf("%x", (int) y);
。 傳遞給printf
值為int
類型的0xFFFF
。 從技術上講, %x
格式需要一個unsigned int
參數,但是非負的int
值也可以(除非我缺少一些技術性)。 輸出為0xFFFF
。
在第二種情況下也會發生向int
轉換。 即您的printf("%x", (signed short) y);
等效於printf("%x", (int) (signed short) y);
。 0xFFFF
到(signed short)
0xFFFF
(signed short)
的轉換是實現定義的,因為0xFFFF
顯然超出了平台上帶signed short
0xFFFF
的范圍。 但最有可能產生負值( -1
)。 當轉換為int
它會產生與int
類型相同的負值(同樣,對於32位int
, -1
表示為0xFFFFFFFF
)。 進一步的行為是不確定的,因為您要為格式說明符%x
傳遞一個負int
值,這需要unsigned int
參數。 將%x
與負int
值一起使用是非法的。
換句話說,您的第二個printf
正式打印出不可預測的垃圾。 但實際上,以上解釋了0xFFFFFFFF
來源。
讓我們將其分解為更小的部分:
鑒於
unsigned short y = 0xFFFF;
假設兩個字節的unsigned short
最大值為2^16-1
,實際上為0xFFFF
。
當我打印時
printf("%x", y);
由於默認參數提升 (因為printf()
是可變函數), y
值隱式提升為int
類型。 使用%x
格式指定的格式,將其視為unsigned int
。 假設常見的二補碼表示形式和四字節的int
類型,這意味着當最高有效位設置為零時, int
和unsigned int
的位模式完全相同。
但是當我打印
printf("%x", (signed short)y);
您所做的事情被強制轉換為帶符號的類型,該類型不能表示0xFFFF
值。 標准轉換等轉換是實現定義的 ,因此您可以獲得任何結果。 隱式轉換為int
您顯然具有32位的位模式,表示為0xFFFFFFFF
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.