为什么,当以十六进制形式将数字打印为前导零的8位数字时,%#08X不显示与0x%08X相同的结果?
当我尝试使用前者时,08格式标志被删除,并且仅使用8不能工作。
为什么,当以十六进制形式将数字打印为前导零的8位数字时,%#08X不显示与0x%08X相同的结果?
当我尝试使用前者时,08格式标志被删除,并且仅使用8不能工作。
当前回答
#导致0x(或0x对于%#X)在输出前加上,除非值为0,所以如果您希望0x总是出现在输出中,就不应该使用#。
您可以使用width字段与0标志结合使用来生成前导零:%08x将前导零的数字填充为8。如果您希望所有32位值输出一致,请使用“0x08x”。
您还可以使用精度字段:%。8x将前导为零的数字填充为总共8位数字。因此,你也可以使用“0x%”。为了你的目的。
如果前缀是作为转换的一部分生成的,那么这些转换规范就会有所不同,例如0x表示#,-表示有符号转换中的负数,其长度计入宽度,但不计入精度说明符。此外,精度场可以与宽度场组合:
printf("|%10x|", 256) // outputs | 100|
printf("|%010x|", 256) // outputs |0000000100|
printf("|%#010x|", 256) // outputs |0x00000100|
printf("|%10.8x|", 256) // outputs | 00000100|
printf("|%#10.8x|", 256) // outputs |0x00000100|
printf("|0x%.8x|", 256) // outputs |0x00000100|
printf("|%10x|", 0) // outputs | 0|
printf("|%010x|", 0) // outputs |0000000000|
printf("|%#010x|", 0) // outputs |0000000000|
printf("|%10.8x|", 0) // outputs | 00000000|
printf("|%#10.8x|", 0) // outputs | 00000000|
printf("|0x%.8x|", 0) // outputs |0x00000000|
我建议使用最后一个:“0x%.8x”。
其他回答
%#08X转换必须在值之前加上0X;这是标准要求的。标准中没有证据表明#应该改变规范中08部分的行为,除了0X前缀被算作长度的一部分(所以您可能想要/需要使用%#010X。如果像我一样,您希望十六进制显示为0x1234CDEF,那么您必须使用0x%08X来实现所需的结果。您可以使用%#。8X也应该插入前导0。
尝试以下代码的变体:
#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 v10.7.5 (Lion)上,输出是:
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) . ...
(强调)。
注意,使用%#X将使用大写字母作为十六进制数字,并使用0X作为前缀;使用%#x将使用小写字母作为十六进制数字,并使用0x作为前缀。如果您希望0x作为前缀和大写字母,则必须单独编码0x: 0x%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肯定是有理由的(但对于32位代码,你会使用8)。
“0x”计入8个字符的计数。你需要“%#010x”。
注意,#没有将0x附加到0 -结果将是0000000000 -所以你可能实际上应该使用“0x%08x”。
#部分在输出字符串中提供了一个0x。0和x计数在08部分列出的“8”字符。如果你想要它是相同的,你需要要求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
#导致0x(或0x对于%#X)在输出前加上,除非值为0,所以如果您希望0x总是出现在输出中,就不应该使用#。
您可以使用width字段与0标志结合使用来生成前导零:%08x将前导零的数字填充为8。如果您希望所有32位值输出一致,请使用“0x08x”。
您还可以使用精度字段:%。8x将前导为零的数字填充为总共8位数字。因此,你也可以使用“0x%”。为了你的目的。
如果前缀是作为转换的一部分生成的,那么这些转换规范就会有所不同,例如0x表示#,-表示有符号转换中的负数,其长度计入宽度,但不计入精度说明符。此外,精度场可以与宽度场组合:
printf("|%10x|", 256) // outputs | 100|
printf("|%010x|", 256) // outputs |0000000100|
printf("|%#010x|", 256) // outputs |0x00000100|
printf("|%10.8x|", 256) // outputs | 00000100|
printf("|%#10.8x|", 256) // outputs |0x00000100|
printf("|0x%.8x|", 256) // outputs |0x00000100|
printf("|%10x|", 0) // outputs | 0|
printf("|%010x|", 0) // outputs |0000000000|
printf("|%#010x|", 0) // outputs |0000000000|
printf("|%10.8x|", 0) // outputs | 00000000|
printf("|%#10.8x|", 0) // outputs | 00000000|
printf("|0x%.8x|", 0) // outputs |0x00000000|
我建议使用最后一个:“0x%.8x”。
您总是可以使用“%p”来显示8位的十六进制数。
int main (void)
{
uint8_t a;
uint32_t b;
a = 15;
b = a << 28;
printf("%p", b);
return 0;
}
输出:
0xf0000000