簡體   English   中英

負符號 8 位 integer 的十六進制表示

[英]Hexadecimal representation of a negative signed 8-bit integer

在我的程序的一部分中,我必須管理有符號的 8 位整數。 使用printf%d格式將它們顯示為小數沒有問題。

但是,當涉及到十六進制表示時,負int8_t變量的格式不顯示為 8 位十六進制 ( 0xXX ),而是顯示為32 位十六進制 ( 0xFFFFFFXX )。

這是描述我的問題的代碼片段:

#include <stdio.h>
#include <stdint.h>

int main()
{
    int8_t value = 0;
    
    printf("t = %d = 0x%02X\n", value, value);
    t = 127;
    printf("t = %d = 0x%02X\n", value, value);
    t = -128;
    printf("t = %d = 0x%02X\n", value, value);
    
    return 0;
}

編譯和執行給出:

t = 0 = 0x00
t = 127 = 0x7F
t = -128 = 0xFFFFFF80

我想得到0x80而不是0xFFFFFF80 我做錯了什么? 如何將負符號 8 位 integer 顯示為 8 位十六進制?

有問題的“符號擴展”正在發生,因為對於您的%X格式說明符,預期的參數類型是int大小,因此您的int_8參數在被適當提升(和符號擴展)后,然后打印為“完整-大小'無符號integer。

您可以通過在格式中添加hh長度修飾符來防止后一部分,這表明相應的參數是char大小,因此只會打印最低有效字節:

#include <stdio.h>
#include <stdint.h>

int main()
{
    int8_t value = 0;

    printf("t = %d = 0x%02hhX\n", value, value);
    value = 127;
    printf("t = %d = 0x%02hhX\n", value, value);
    value = -128;
    printf("t = %d = 0x%02hhX\n", value, value);

    return 0;
}

進一步參考


注意:正如這里的評論和其他答案中所指出的,對有符號類型的參數使用%X格式說明符(帶或不帶長度修飾符)在形式上是未定義的行為(盡管它可能適用於絕大多數現代系統)。

為了避免這種潛在的 UB,實現目標的更好方法是將int8_t參數顯式轉換為無符號等效項(在您的情況下具有相同的位大小 - 或uint8_t )。 然后,當應用“默認參數提升”時,它將在沒有符號擴展的情況下執行(因為uint8_t的所有可能值都可以在int中表示); 因此,無需將hh長度修飾符添加到您的格式中,因為不會設置結果unsigned int值的高位(添加)。

此代碼以明確定義的方式給出您想要的結果:

int main()
{
    int8_t value = 0;
    printf("t = %d = 0x%02X\n", value, (uint8_t)value);
    value = 127;
    printf("t = %d = 0x%02X\n", value, (uint8_t)value);
    value = -128;
    printf("t = %d = 0x%02X\n", value, (uint8_t)value);
    return 0;
}

當小於int的 integer 類型傳遞給可變參數 function (如printf時,它們被提升為int類型。 因此,值為 -1 且表示為 0xff 的int8_t變為值為 -1 且表示為 0xffffffff 的int

這就是為什么您在使用%x時看到的值,它期望並打印一個int 要表明您正在打印一個char值,請使用%hhx它將在打印之前將該值轉換為char

printf("t = %d = 0x%02hhX\n", value, value);

或者,您可以將該值強制轉換為uint8_t以更好地匹配%x的預期:

printf("t = %d = 0x%02X\n", value, (uint8_t)value);

此代碼具有未定義的行為 %X格式說明符的行為僅由語言標准針對unsigned int類型的參數的情況定義。 您提供了一個int8_t

In practice you may (but this is not guaranteed) find that the printf function tries to read an unsigned int from the location where integer arguments are stored, and what you are seeing corresponds to how that location gets filled up by an int8_t value.

這是因為默認提升 integer arguments。 您需要使用正確的格式說明符並強制轉換:

int main(void)
{
    int8_t value = 0;
    
    printf("t = %d = %02" PRIx8 "\n", value, value);
    value = 127;
    printf("t = %d = 0x%02" PRIx8 "\n", value,(uint8_t)value);
    value = -128;
    printf("t = %d = 0x%02" PRIx8 "\n", value, (uint8_t)value);
    
    return 0;
}

https://godbolt.org/z/jMqhz5156

我想得到 0x80 而不是 0xFFFFFF80。

0x80表示值 +128 10

要將 -128 打印為0x80而沒有未定義的行為,請不要嘗試使用"%X"打印負數。 先轉換成正數。

t = -128;
// printf("t = %d = 0x%02X\n", value, value); 
printf("t = %d = 0x%02X\n", value, (uint8_t) value); 

(uint8_t) value通過添加 256 來轉換int8_t負值。將uint8_t傳遞給 ... 參數將轉換為值在 [0...255] 范圍內的int

"%X"需要一個unsigned int傳遞給讀取為unsigned...參數是可以的,只要該值在 C17dr §6.5.2.2 6 中都可以表示(例如正數)。

迂腐地,不依賴 §6.5.2.2 6:

printf("t = %d = 0x%02X\n", value, (unsigned) (uint8_t) value); 

暫無
暫無

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

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