Bug in handling of "1$", "2$" in printf format

Brian Inglis Brian.Inglis@Shaw.ca
Sat Dec 7 04:37:03 GMT 2024


On 2024-12-06 19:16, Keith Thompson via Cygwin wrote:
> The use of "1$", "2$" et al in printf format specifiers is a
> POSIX-specific feature.
> 
> On Cygwin (newlib) this is handled correctly in most cases, but one
> example I tried misbehaves.
> The output is correct on other implementations, including glibc and
> musl on Ubuntu.
> 
> This C program:
> 
> #include <stdio.h>
> int main(void) {
>      long long a = 123456789876543210;
>      double b=1.0/3;
>      printf("a:%2$8.8lld b:%1$10.2g\n", b, a);
> }
> 
> should produce this output:
> 
> a:123456789876543210 b:      0.33
> 
> Under Cygwin (fully updated), with "gcc c.c -o c && ./c", the output is:
> 
> a:140732550844138 b:  7.1e-315
> 

Confirmed with gcc 12.4 and minor tweaks to constant data types: printf is 
ignoring arg positions:

$ gcc --version && tail posnprintf.c && gcc -o posnprintf{,.c} && ./posnprintf
gcc (GCC) 12.4.0
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

#define I18LL 123456789876543210LL
#define THIRD 1.0/3.0
int main(void) {
     long long	a = I18LL;
     double	b = THIRD;
     printf("expected\ta:%18lld\tb:%10.6f\n",	I18LL, THIRD);
     printf("parameters\ta:%8.8lld\tb:%10.2g\n",		a, b);
     printf("positional\ta:%2$8.8lld\tb:%1$10.2g\n",	b, a);
     printf("ignoreposn\tb:%8.8lld\ta:%10.2g\n",		b, a);
}
posnprintf.c: In function ‘main’:
posnprintf.c:12:33: warning: format ‘%lld’ expects argument of type ‘long long 
int’, but argument 2 has type ‘double’ [-Wformat=]
    12 |     printf("ignoreposn\tb:%8.8lld\ta:%10.2g\n",         b, a);
       |                           ~~~~~~^                       ~
       |                                 |                       |
       |                                 long long int           double
       |                           %8.8f
posnprintf.c:12:43: warning: format ‘%g’ expects argument of type ‘double’, but 
argument 3 has type ‘long long int’ [-Wformat=]
    12 |     printf("ignoreposn\tb:%8.8lld\ta:%10.2g\n",         b, a);
       |                                      ~~~~~^                ~
       |                                           |                |
       |                                           double           long long int
       |                                      %10.2lld
expected	a:123456789876543210	b:  0.333333
parameters	a:123456789876543210	b:      0.33
positional	a:4599676421641834218	b:  2.1e-300
ignoreposn	b:4599676419421066581	a:  2.1e-300

-- 
Take care. Thanks, Brian Inglis              Calgary, Alberta, Canada

La perfection est atteinte                   Perfection is achieved
non pas lorsqu'il n'y a plus rien à ajouter  not when there is no more to add
mais lorsqu'il n'y a plus rien à retirer     but when there is no more to cut
                                 -- Antoine de Saint-Exupéry


More information about the Cygwin mailing list