Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 17 Sep 2010 21:43:34 +1000 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        "David O'Brien" <obrien@FreeBSD.org>
Cc:        svn-src-head@FreeBSD.org, svn-src-all@FreeBSD.org, src-committers@FreeBSD.org, Jilles Tjoelker <jilles@stack.nl>
Subject:   Re: svn commit: r212374 - head/usr.bin/printf
Message-ID:  <20100917212708.Y771@delplex.bde.org>
In-Reply-To: <20100917002101.GA13653@dragon.NUXI.org>
References:  <201009091927.o89JReXm022426@svn.freebsd.org> <20100909195302.GA48144@stack.nl> <20100917002101.GA13653@dragon.NUXI.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 16 Sep 2010, David O'Brien wrote:

> ...
> Interestingly, we may not be compliant with susv3 if I am reading this
> correctly:
>
>    The printf utility is required to notify the user when conversion
>    errors are detected while producing numeric output; thus, the
>    following results would be expected on an implementation with 32-bit
>    twos-complement integers when %d is specified as the format operand:
>
>    Argument      Standard Output   Diagnostic Output
>    5a            5                 printf: "5a" not completely converted
>    9999999999    2147483647        printf: "9999999999" arithmetic overflow
>    -9999999999   -2147483648       printf: "-9999999999" arithmetic overflow
>    ABC           0                 printf: "ABC" expected numeric value
>
>
>  $ uname -m
>  i386
>  $ for A in 5a 9999999999 -9999999999 ABC do /usr/bin/printf "%d\n" $A ; done
>  printf: 5a: not completely converted
>  5
>  9999999999
>  -9999999999
>  printf: ABC: expected numeric value
>  0
>
> Though this is in the "informative" section, so maybe this is just one
> set of compliant output.  Though It is my read that printf(1) should
> behave like printf(3), which the above does not for these long long int
> values.

The implementation actually uses [u]quad_t integers (blech -- it should use
[u]intmax_t integers).  This may be conformant.  POSIX has the general
bug of making low-quality implementations, that only support plain integers
for command-line options, conformant, and may even require not supporting
larger integers in some cases, but hopefully it doesn't require this
bug for printf(1).

>    #include <stdio.h>
>    int
>    main(void)
>    {
>            printf("%d\n", 9999999999);
>            printf("%d\n", -9999999999);
>            return 0;
>    }

Restricting to plain int for printf(1) would be less than useful, since
unlike printf(3), it has no way of controlling the integer size -- even
"%ld" format is "illegal" (should be "invalid") for printf(1).  Users
wanting to handle large integers would have to use floating point with
"%.0f" format, which has some advantages anyway, but printf(1)'s FP
format is only double precision, so it doesn't work right for integers
>= 2**53 even on arches that have working long double precision.
Rounding errors are also not reported for integers >= 2**53 when
represented as doubles:

$ printf %.0f\\n 9999999999999999
10000000000000000

and its documentation is slightly wrong in saying (re-quoting the above):

>    The printf utility is required to notify the user when conversion
>    errors are detected while producing numeric output; thus ...

since in the floating point case, it is very unusual for there not to be
a rounding error (e.g., 0.1 is not exactly representable in base 2 FP),
so reporting _all_ rounding errors would be wrong.  In fact, it doesn't
seem to be done at all for rounding errors.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20100917212708.Y771>