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?
The Format specifier is a string used in the formatted input and output functions. The format string determines the format of the input and output. The format string always starts with a '%' character.
To print integer number in Hexadecimal format, "%x" or "%X" is used as format specifier in printf() statement. "%x" prints the value in Hexadecimal format with alphabets in lowercase (a-f). "%X" prints the value in Hexadecimal format with alphabets in uppercase (A-F).
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%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 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With