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 standard seems to be written this way:
%#xand%#otry to guarantee that the output can be parsed correctly usingstrtolwithbase = 0.In these cases, the
#flag adds as few extra characters as possible. For example, 0 is printed as0because 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
0xalways, you could often simply write something like0x%x. Hence%#xwould seem to be useful only in those special cases in which you really want the special handling of 0. But the pre-pending of0xdoesn’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 likeprintf( "%12s", hexstr);Fortunately justifying with0rather than spaces using something likeprintf( "0x%012x", hexstr);works as expected producing valid hex digits for a parser.Now the way
%#xis specified to work makes a lot of sense in isolation. And the way something like%010xis 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, having0,rather than0x0is not an issue.But there is no need to combine
%#xand%010x. You could just write0x%08xto do what you want.