Why is 0 (zero) printed without leading "0x" with C printf format "%#x"?
The standard seems to be written this way:
%#x
and%#o
try to guarantee that the output can be parsed correctly usingstrtol
withbase = 0
.In these cases, the
#
flag adds as few extra characters as possible. For example, 0 is printed as0
because there is no need to add the extra0x
. 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 like0x%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 of0x
doesn't work well with default field width specifiers eg)0x%12x
is 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 likeprintf( "%12s", hexstr);
Fortunately justifying with0
rather than spaces using something likeprintf( "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.
David Poole
Firmware engineer working on routers with Cradlepoint in Boise, Idaho. Work in C, Python, Linux kernel, GIS, low level firmware.
Updated on June 13, 2022Comments
-
David Poole almost 2 years
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?