Consider the following invocation of printf():
printf("%.-1f", 34.14);
it specifies a negative precision value of -1. Making this call with glibc, we get:
%0.-1f
is this correct? If so, why?
Consider the following invocation of printf():
printf("%.-1f", 34.14);
it specifies a negative precision value of -1. Making this call with glibc, we get:
%0.-1f
is this correct? If so, why?
The wording changed between C11 and C17/18. In C17/18 it says:
§7.21.6.1 The
fprintffunction
4. [...] The precision takes the form of a period (.) followed either by an asterisk*(described later) or by an optional nonnegative decimal integer; [...]
The way I read it, the behavior when using a negative integer is not defined.
This is not a breaking change since it does not make previously valid programs invalid. The intent was never to allow negative values as pointed out in DR220 - Definition of "decimal integer" / N32079:
The term "decimal integer" is defined neither in the Standard nor in ISO 2382-1. Therefore it is not possible to tell whether, in each case:
- the value may be zero
- a non-significant leading zero digit may be used
- the value may be negative.
Suggested Technical Corrigendum
Add a new paragraph to 7.1.1:
[#x] A decimal integer is a sequence of digits which may begin with one or more zeros, but is nonetheless interpreted as decimal, not octal.
Technical Corrigendum
In 7.19.6.1P4, which reads in part: "[...] or by an optional decimal integer [...]"
change "decimal integer" to "non-negative decimal integer".
0 in pre C17/18 mode which supports my assumption. I didn't want to put this assumption in the answer though.printf("%.+1f\n", 34.14);. It probably should have said “unsigned decimal integer” or “nonempty sequence of digits”.I believe that's an error. the C standard (ISO/IEC 9899:1999) says:
§7.19.6.1
Each conversion specification is introduced by the character %. After the %, the following appear in sequence:
... snip ...
- An optional precision ... The precision takes the form of a period (.) followed either by an asterisk * (described later) or by an optional decimal integer;
... snip ...
- As noted above, a field width, or precision, or both, may be indicated by an asterisk. In this case, an int argument supplies the field width or precision. ... A negative precision argument is taken as if the precision were omitted.
Well, -1 is a negative integer; so it can legitimately be specified literally in the format string; and while the text explaining what to do with a negative specified precision appears in the clause regarding asterisk-indicated values - surely it should be the same logic as for literally-specified values (just like it is for widths).
So, I believe the precision value should be ignored in this cause, and the format string is the equivalent of "%f", so the output should be:
34.140000
(default precision of 6)