背景:我有许多脚本通过查找前导“0x”来解析查找十六进制数字的日志文件。我们的嵌入式C库改为新的printf。新的printf比我们之前的标准更符合标准,我的脚本破了。
在Linux机上:
#include <stdio.h>
int main( void )
{
printf( "%#010x\n", 0 );
printf( "%#010x\n", 1 );
return 0;
}
输出(使用glibc)是:
0000000000
0x00000001
我们的firmwware的输出是:
0x00000000
0x00000001
从printf(3)开始,在'#'标志字符上: “对于x和X转换,非零结果的前缀为字符串”0x“(或X转换为”0X“)。”
我好奇为什么。如果没有挖掘C标准文件或为标准委员会成员购买午餐,为什么不在零价值论证中使用前导0x?
答案 0 :(得分:24)
标准似乎是这样写的:
%#x
和%#o
尝试保证使用strtol
base = 0
正确解析输出。
在这些情况下,#
标志会将添加为可能的额外字符。例如,0打印为0
,因为无需添加额外的0x
。如果你 not 指定最小字段宽度和0-padding,这很有意义。
如果您想要始终添加0x
,您通常可以简单地编写0x%x
之类的内容。因此%#x
在您真正想要特殊处理0的特殊情况下似乎只有 。但{{1}的预先处理使用默认字段宽度说明符不能很好地工作,例如,0x
由0x和十六进制数字之间的空白右对齐,这在这种情况下不太可能是想要的。对于这种情况,需要使用sprintf进行额外的准备传递,因此像0x%12x
这样的十六进制字符串可以是空格右对齐,例如"0x2ac2"
幸运的是使用printf( "%12s", hexstr);
来证明是正确的,而不是使用某些空格像0
一样按预期工作,为解析器生成有效的十六进制数字。
现在printf( "0x%012x", hexstr);
指定工作的方式在隔离方面很有意义。像%#x
这样的工作方式可以单独使用。你正在组合这两个修饰语,最终结果可能是奇怪的。对于另一个应用程序,例如自动生成用于初始化表的简洁C代码,使用%010x
而不是0,
不是问题。
但无需合并0x0
和%#x
。你可以写%010x
来做你想做的事。