十六进制的printf()格式


190

这比一个重要的问题更有趣,但是为什么在将十六进制打印为带有前导零的8位数字时,为什么%#08X显示的结果不相同0x%08X

当我尝试使用前者时,08格式设置标记已删除,并且只适用于8

再一次,我只是好奇。


3
你是说0x%.8X吗 这导致零填充。(这0x只是序言,但您可能已经意识到这一点)。
WhozCraig

Answers:


282

#部分0x在输出字符串中给您一个。在0x反对在列出的“8”字计数08的一部分。如果您希望相同,则需要输入10个字符。

int i = 7;

printf("%#010x\n", i);  // gives 0x00000007
printf("0x%08x\n", i);  // gives 0x00000007
printf("%#08x\n", i);   // gives 0x000007

同样更改的大小写x也会影响输出字符的大小写。

printf("%04x", 4779); // gives 12ab
printf("%04X", 4779); // gives 12AB

第一行为我输出14F0x00000007。第二和第三部作品按书面规定。
Quantumpotato 2014年

@quantumpotato-太奇怪了。第一和第三行是相同的,除了它们应产生的0的数目。您的编译器/系统/代码行产生了什么?在打印的那一行中,您是否有任何一行14F
2014年

19
请注意,如果使用i = 0;,版本%#将不包含0x前缀。
乔纳森·勒夫勒

但是十六进制如何:0x43A66C31C68491C0我尝试了以下操作:__int64 int64 = 0x43A66C31C68491C0; printf_s(“%#15X%d”,int64,int64); 但是输出是0XC68491C0,而不是0x43A66C31C68491C0
123iamking '16

关于上面的十六进制0x43A66C31C68491C0,我已经解决了,解决方案是0x%I64X而不是%#15X
123iamking '16

53

“ 0x”计入八个字符数。你需要"%#010x"

请注意,#没有在0X追加到0 -结果将是0000000000-所以你可能实际上应该只使用"0x%08x"反正。


34

所述%#08X转换必须与前面的值0X; 这是标准要求的。在标准中没有证据表明#应当改变08规范部分的行为,除了0X前缀是长度的一部分(因此,您可能希望/需要使用%#010X。如果像我一样,您喜欢用十六进制表示为0x1234CDEF,则必须使用0x%08X来获得所需的结果。可以使用%#.8X,并且还应该插入前导零。

请尝试以下代码的变体:

#include <stdio.h>

int main(void)
{
    int j = 0;
    printf("0x%.8X = %#08X = %#.8X = %#010x\n", j, j, j, j);
    for (int i = 0; i < 8; i++)
    {
        j = (j << 4) | (i + 6);
        printf("0x%.8X = %#08X = %#.8X = %#010x\n", j, j, j, j);
    }
    return(0);
}

在RHEL 5计算机上以及Mac OS X(10.7.5)上,输出为:

0x00000000 = 00000000 = 00000000 = 0000000000
0x00000006 = 0X000006 = 0X00000006 = 0x00000006
0x00000067 = 0X000067 = 0X00000067 = 0x00000067
0x00000678 = 0X000678 = 0X00000678 = 0x00000678
0x00006789 = 0X006789 = 0X00006789 = 0x00006789
0x0006789A = 0X06789A = 0X0006789A = 0x0006789a
0x006789AB = 0X6789AB = 0X006789AB = 0x006789ab
0x06789ABC = 0X6789ABC = 0X06789ABC = 0x06789abc
0x6789ABCD = 0X6789ABCD = 0X6789ABCD = 0x6789abcd

我对0的处理感到有些惊讶;我不清楚为什么0X省略前缀,但是在两个单独的系统中,它必须是标准的。它证实了我对这种#选择的偏见。


零的处理符合标准。

ISO / IEC 9899:2011 §7.21.6.1 fprintf功能

¶6标志字符及其含义是:
...
#结果被转换为“替代形式”。...对于x(或X)转换,非零结果以0x(或0X)为前缀。...

(已添加重点。)


注意,using %#X将使用大写字母作为十六进制数字并0X作为前缀;using %#x将使用小写字母作为十六进制数字并0x作为前缀。如果您希望将其0x作为前缀和大写字母,则必须分别编码0x0x%X。当然,可以根据需要添加其他格式修饰符。

对于打印地址,请使用<inttypes.h>标题,uintptr_t类型和PRIXPTR格式宏:

#include <inttypes.h>
#include <stdio.h>

int main(void)
{
    void *address = &address;  // &address has type void ** but it converts to void *
    printf("Address 0x%.12" PRIXPTR "\n", (uintptr_t)address);
    return 0;
}

输出示例:

Address 0x7FFEE5B29428

根据长度选择毒药-我发现12精度对于运行macOS的Mac上的地址非常适用。结合.指定最小精度(数字),它可以可靠地格式化地址。如果您将精度设置为16,那么根据我在Mac上的经验,多余的4位数字始终为0,但是在便携式64位代码中肯定需要使用16而不是12(但是对于8位数字,则使用8 32位代码)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.