为什么打印0(零)时没有前导“;0x";使用C printf格式";%#x";?
背景:我有很多脚本,它们通过查找前导“0x”来解析日志文件,查找十六进制数。我们的嵌入式C库更改为新的printf。新的printf比以前的printf更符合标准,我的脚本也坏了 在Linux机箱上:为什么打印0(零)时没有前导“;0x";使用C printf格式";%#x";?,c,hex,printf,C,Hex,Printf,背景:我有很多脚本,它们通过查找前导“0x”来解析日志文件,查找十六进制数。我们的嵌入式C库更改为新的printf。新的printf比以前的printf更符合标准,我的脚本也坏了 在Linux机箱上: #include <stdio.h> int main( void ) { printf( "%#010x\n", 0 ); printf( "%#010x\n", 1 ); return 0; } 我们firmwware上的输出为: 0x00000000 0
#include <stdio.h>
int main( void )
{
printf( "%#010x\n", 0 );
printf( "%#010x\n", 1 );
return 0;
}
我们firmwware上的输出为:
0x00000000
0x00000001
从printf(3)中,在“#”标志字符上:
对于x和x转换,非零结果前面有字符串“0x”(对于x转换为“0x”)
我很好奇为什么。如果不深入阅读C标准文件或为标准委员会成员购买午餐,为什么不在零值论点上使用前导0x?标准似乎是这样写的:
和%#x
尝试使用%#o
和strtol
确保可以正确解析输出base=0
- 在这些情况下,
标志会添加尽可能少的额外字符。例如,0被打印为#
,因为不需要添加额外的0
。如果不指定最小字段宽度和0填充,则这很有意义0x
- 如果希望始终添加
,通常可以编写类似0x
的内容。因此,0x%x
似乎只有在您真正需要对0进行特殊处理的特殊情况下才有用。但是,%#x
的预挂起与默认字段宽度说明符(例如,0x
在0x和十六进制数字之间的空格正确对齐,这在这种情况下不太可能是需要的。在这种情况下,需要使用sprintf进行额外的准备过程,因此像0x%12x
这样的十六进制字符串可以用像“0x2ac2”
printf(“%12s”,hexstr)这样的东西进行空格右对齐代码>幸运的是,使用
而不是使用0
printf(“0x%012x”,hexstr)之类的空格来进行证明代码>按预期工作,为解析器生成有效的十六进制数字
%#x
指定为独立工作的方式非常有意义。像%010x
这样的东西被指定为独立工作的方式非常有意义。您将这两个修饰符组合在一起,最终结果可能会很奇怪。对于另一个应用程序,比如自动生成整洁的C代码来初始化表,使用0,
而不是0x0
不是问题
但是没有必要将
%#x
和%010x
组合在一起。您可以只编写0x%08x
来执行所需操作。胡乱猜测:0是0,不考虑基数,因此无需指定它。值得注意的是,通过编写“0x%08x”
,您可以获得始终包含前导0x
的行为,然而,从总是包含前导的0x
的库中获取所描述的标准行为将更为棘手。也许标准委员会正在优化一个更难获得的案例,而不是一个绝对最常见的案例?(当然,你不能将“%#10x”
更改为“0x%8x”
,但是,很难想象有人希望看到0x0
,而不使用零填充。)(HTML)或(PDF)中没有提到这一点。在发布答案后,我注意到@ruakh已经在评论中给出了基本相同的信息。抱歉。没有必要道歉。答案比评论好。我把我的想法作为评论,而不是回答,因为我知道它们不可能是完整的;但是你的回答要彻底得多,而且很有意义。谢谢你的回答和评论!与strtol兼容的想法是有道理的。现在,我需要将大量代码更改为0x%08x。为什么1
也没有这种行为?它与0
一样明确。不需要添加额外的0x
。
0x00000000
0x00000001