簡體   English   中英

簽名擴展查詢以防萬一

[英]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類型。 在物理上不可能傳遞shortchar可變參數。 隱式轉換為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類型,這意味着當最高有效位設置為零時, intunsigned int的位模式完全相同。

但是當我打印

printf("%x", (signed short)y);

您所做的事情被強制轉換為帶符號的類型,該類型不能表示0xFFFF值。 標准轉換等轉換是實現定義的 ,因此您可以獲得任何結果。 隱式轉換為int您顯然具有32位的位模式,表示為0xFFFFFFFF

暫無
暫無

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

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