printf:为什么 %x 不打印前导 0x(与 %a 相对)?
printf: why doesn't %x print leading 0x (as opposed to %a)?
此代码:
#include <stdio.h>
int main(void)
{
printf("%a\n", 1.0);
printf("%x\n", 93);
}
输出:
0x1p+0
5d
为什么不0x5d
?
有人知道原理吗?
注意:this 问题不完全相同,因为它是关于 %#x
。
问题原因:对于%x
不能总是“在初始化器中反馈给C”:
$ cat t324.c
#include <stdio.h>
int main(void)
{
printf(X);
}
$ gcc t324.c -DX="\"double x = %a;\", 10.0" && ./a.exe | gcc -xc - -c
<nothing>
$ gcc t324.c -DX="\"int x = %x;\", 10" && ./a.exe | gcc -xc - -c
<stdin>:1:9: error: ‘a’ undeclared here (not in a function)
我认为您可以选择是否使用 0x。当您使用 %x
时,您会收到原始的十六进制数。但是当您使用 %#x
时,您会收到带有 0x
前缀的十六进制数。视情况而定。
正如 @Jack05, the '#' character makes the difference. The manual of printf 解释的转换:
Each conversion specification is introduced by the character %, and ends with
a conversion specifier. In between there may be (in this order) zero or more
flags, an optional minimum field width, an optional precision and an optional
length modifier.
The overall syntax of a conversion specification is:
%[$][flags][width][.precision][length modifier]conversion
如果标志符设置为'#',则:
For x and X conversions, a nonzero result has the string
"0x" (or "0X" for X conversions) prepended to it.
对于'a'或'A'转换,
the double argument is converted to hexadecimal notation
(using the letters abcdef) in the style [-]0xh.hhhhp±d;
for A conversion the prefix 0X, the letters ABCDEF
"%a"
、"%A"
以 "0x"
、"0X"
开头,以帮助区别于 "%f"
、"%e"
、"%g"
, "%F"
, ...
注意 "%a"
而不是说 "%e"
,影响 2 个部分,prefix 和 base 字母:"0x"
和 "p"
而不是 ""
和 "e"
.
"%a"
在内存价格下降后表现良好。
"%x"
前导没有前缀,因为代码经常需要连接十六进制输出,如 printf("%08x%08x", a32, b32);
一样,先加上 "0x"
前缀再如 "0x%08x%08x"
是微不足道的。不为十六进制输出添加前缀作为默认值肯定更常见,在当天(1970 年代)因为每个字节 costs.
使用 #
和 "%x"
就像在 "%#x"
中那样 总是 前缀输出。当值为 non-zero.
时出现前缀(与数字相同)
为清楚起见,我发现小写 x
和大写十六进制数字很有用。
// v------ lower --------v
printf("0x%08X\n", 0u-1u); // 0xFFFFFFFF
// ^-- upper ---------^^^^^^^^
此代码:
#include <stdio.h>
int main(void)
{
printf("%a\n", 1.0);
printf("%x\n", 93);
}
输出:
0x1p+0
5d
为什么不0x5d
?
有人知道原理吗?
注意:this 问题不完全相同,因为它是关于 %#x
。
问题原因:对于%x
不能总是“在初始化器中反馈给C”:
$ cat t324.c
#include <stdio.h>
int main(void)
{
printf(X);
}
$ gcc t324.c -DX="\"double x = %a;\", 10.0" && ./a.exe | gcc -xc - -c
<nothing>
$ gcc t324.c -DX="\"int x = %x;\", 10" && ./a.exe | gcc -xc - -c
<stdin>:1:9: error: ‘a’ undeclared here (not in a function)
我认为您可以选择是否使用 0x。当您使用 %x
时,您会收到原始的十六进制数。但是当您使用 %#x
时,您会收到带有 0x
前缀的十六进制数。视情况而定。
正如 @Jack05, the '#' character makes the difference. The manual of printf 解释的转换:
Each conversion specification is introduced by the character %, and ends with a conversion specifier. In between there may be (in this order) zero or more flags, an optional minimum field width, an optional precision and an optional length modifier.
The overall syntax of a conversion specification is:%[$][flags][width][.precision][length modifier]conversion
如果标志符设置为'#',则:
For x and X conversions, a nonzero result has the string "0x" (or "0X" for X conversions) prepended to it.
对于'a'或'A'转换,
the double argument is converted to hexadecimal notation (using the letters abcdef) in the style [-]0xh.hhhhp±d; for A conversion the prefix 0X, the letters ABCDEF
"%a"
、"%A"
以 "0x"
、"0X"
开头,以帮助区别于 "%f"
、"%e"
、"%g"
, "%F"
, ...
注意 "%a"
而不是说 "%e"
,影响 2 个部分,prefix 和 base 字母:"0x"
和 "p"
而不是 ""
和 "e"
.
"%a"
在内存价格下降后表现良好。
"%x"
前导没有前缀,因为代码经常需要连接十六进制输出,如 printf("%08x%08x", a32, b32);
一样,先加上 "0x"
前缀再如 "0x%08x%08x"
是微不足道的。不为十六进制输出添加前缀作为默认值肯定更常见,在当天(1970 年代)因为每个字节 costs.
使用 #
和 "%x"
就像在 "%#x"
中那样 总是 前缀输出。当值为 non-zero.
为清楚起见,我发现小写 x
和大写十六进制数字很有用。
// v------ lower --------v
printf("0x%08X\n", 0u-1u); // 0xFFFFFFFF
// ^-- upper ---------^^^^^^^^