Why is the prefix written with octal when using both the #
flag and explicit 0
precision for unsigned int conversions? Is it normal?
I've noticed this and it feels like a bug (I'm not claiming it is).
However I'd like to understand how it works because it's making very little sense to me. Is there a rationale behind?
My best guess so far is that the prefix is handled after the precision. Since an empty output (which is what you get with printing 0 with an explicit precision of 0) doesn't start with "0" the "0" prefix is added. But I would've expected the prefix to be included in the concept of "output" and therefore I'd have expected it to not be displayed.
/* main.c */
#include <stdio.h>
int main()
{
printf("%%u conv: [%#.0u]\n", 0);
printf("%%o conv: [%#.0o]\n", 0);
return (0);
}
Output:
> gcc -o test main.c && ./test
%u conv: []
%o conv: [0]
Highlights from man 3 printf
:
#
flag:The value should be converted to an "alternate form". For o conversions, the first character of the output string is made zero (by prefixing a 0 if it was not zero already). For x and X conversions, a nonzero result has the string "0x" (or "0X" for X conversions) prepended to it. [...]
An optional precision, in the form of a period ('.') followed by an optional decimal digit string. [...] This gives the minimum number of digits to appear for d, i, o, u, x, and X conversions [...].
u
, o
, x
, X
):[...] The precision, if any, gives the minimum number of digits that must appear; if the converted value requires fewer digits, it is padded on the left with zeros. The default precision is 1. When 0 is printed with an explicit precision 0, the output is empty.
This is normal, and specified by the C standard:
#
The result is converted to an ''alternative form''. For o conversion, it increases the precision, if and only if necessary, to force the first digit of the result to be a zero (if the value and precision are both 0, a single 0 is printed). For x (or X) conversion, a nonzero result has 0x (or 0X) prefixed to it. ...
For o
conversion, #
forces a leading zero even if the value and precision are both 0. For x conversion, the leading 0x or 0X is only prefixed to nonzero values.
You can also see that the man page you quoted says something similar: #
with o
forces a leading zero no matter what, while #
with x
or X
only adds a prefix to nonzero values.
Note that o
, x
, and X
are the only integer conversions for which the behavior of #
is defined. Using #
with u
is undefined behavior.