为什么打印 0(零)时没有前导“0x”?使用 C printf 格式“%#x”?

发布于 2024-12-21 04:39:02 字数 563 浏览 0 评论 0原文

背景:我有许多脚本可以解析日志文件,通过查找前导“0x”来查找十六进制数字。我们的嵌入式 C 库更改为新的 printf。新的 printf 比我们以前的 printf 更符合标准,但我的脚本坏了。

在 Linux 机器上:

#include <stdio.h>
int main( void )
{
    printf( "%#010x\n", 0 );
    printf( "%#010x\n", 1 );
    return 0;
}

输出(使用 glibc)是:

0000000000
0x00000001

我们固件上的输出是:

0x00000000
0x00000001

来自 printf(3),在“#”标志字符上: “对于 x 和 X 转换,非零结果的前面会添加字符串“0x”(对于 X 转换则为“0X”)。”

我很好奇为什么。如果不深入研究 C 标准文档或为标准委员会成员买午餐,为什么不在零值参数上使用领先的 0x 呢?

Background: I have a number of scripts that parse log files looking for hex numbers by finding the leading "0x". Our embedded C library changed to a new printf. The new printf is more standards compliant than our previous and my scripts broke.

On a Linux box:

#include <stdio.h>
int main( void )
{
    printf( "%#010x\n", 0 );
    printf( "%#010x\n", 1 );
    return 0;
}

Output (using glibc) is:

0000000000
0x00000001

Output on our firmwware was:

0x00000000
0x00000001

From printf(3), on the '#' flag character:
"For x and X conversions, a nonzero result has the string "0x" (or "0X" for X conversions) prepended to it."

I'm curious why. Without digging through the C standards documents or buying lunch for standards committee members, why not a leading 0x on a zero valued argument?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

洛阳烟雨空心柳 2024-12-28 04:39:02

标准似乎是这样写的:

  • %#x%#o 尝试保证可以使用 strtol 正确解析输出code> 和 base = 0

  • 在这些情况下,# 标志会添加尽可能少的额外字符。例如,0 被打印为 0,因为不需要添加额外的 0x。如果您指定最小字段宽度和 0 填充,这很有意义。

  • 如果您想始终添加 0x,通常可以简单地编写类似 0x%x 的内容。因此,%#x 似乎仅在您确实想要对 0 进行特殊处理的特殊情况下才有用。 0x 的挂起不能很好地与默认字段宽度说明符配合使用,例如)0x%12x 通过 0x 和十六进制数字之间的空格右对齐,这不太可能是这样在那种情况下想要。对于这种情况,需要使用 sprintf 进行额外的准备过程,因此像 "0x2ac2" 这样的十六进制字符串可以使用 printf( "%12s", hexstr); 之类的空格右对齐。 幸运的是,使用 0 而不是使用诸如 printf( "0x%012x", hexstr); 之类的空格进行对齐; 按预期生成有效的十六进制解析器的数字。

现在,指定 %#x 的工作方式在孤立的情况下非常有意义。像 %010x 这样的东西被指定为单独工作是很有意义的。您将这两个修饰符组合起来,最终的结果可以说是很奇怪的。对于另一个应用程序,例如自动生成简洁的 C 代码来初始化表,使用 0, 而不是 0x0 不是问题。

但没有必要将 %#x%010x 结合起来。您只需编写 0x%08x 即可执行您想要的操作。

The standard seems to be written this way:

  • %#x and %#o try to guarantee that the output can be parsed correctly using strtol with base = 0.

  • In these cases, the # flag adds as few extra characters as possible. For example, 0 is printed as 0 because there is no need to add the extra 0x. This makes a lot of sense if you do not specify the minimum field width and 0-padding.

  • If you wanted to add 0x always, you could often simply write something like 0x%x. Hence %#x would seem to be useful only in those special cases in which you really want the special handling of 0. But the pre-pending of 0x doesn't work well with default field width specifiers eg) 0x%12xis right justified by blanks between the 0x and hex digits, which is unlikely to be what's wanted in that case. For this case an extra preparatory pass with sprintf would be required, so a hex string like "0x2ac2" can be white space right justified with something like printf( "%12s", hexstr); Fortunately justifying with 0 rather than spaces using something like printf( "0x%012x", hexstr); works as expected producing valid hex digits for a parser.

Now the way %#x is specified to work makes a lot of sense in isolation. And the way something like %010x is specified to work makes a lot of sense in isolation. You are combining these two modifiers, and the end result is, arguably, strange. For another application, like auto generating neat C code to initialise tables, having 0, rather than 0x0 is not an issue.

But there is no need to combine %#x and %010x. You could just write 0x%08x to do what you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文