Question

Interpreting the format specifier in printf("%.-1f", 34.14)

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?

 3  85  3
1 Jan 1970

Solution

 9

The wording changed between C11 and C17/18. In C17/18 it says:

§7.21.6.1 The fprintf function
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".

2024-07-23
Ted Lyngmo

Solution

 0

I believe that's an error. the C standard (ISO/IEC 9899:1999) says:

§7.19.6.1

  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 ...

  1. 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)

2024-07-23
einpoklum