Robert Elz wrote, on 24 Oct 2020: > > Is there somewhere, anywhere, where it is possible to infer what > range of values printf (the utility, not the C library function) > is expected to handle? > > I can find nothing in the XCU 3.printf page, nor in XBD 5 (and also > not in XBD 12, which would be another plausible place).
You missed XBD 12.1 list item 6? > XBD 14.limits.h gives the minimum allowed value for the maximum value > of an integer (2^31 - 1) (ie: requires at least 32 bit int), but I can > find nothing that says explicitly that that applies to printf the utility. LONG_MAX is the one that applies, via XCU 1.1.2.1 Arithmetic Precision and Operations: Integer variables and constants, including the values of operands and option-arguments, used by the standard utilities listed in this volume of POSIX.1-2017 shall be implemented as equivalent to the ISO C standard signed long data type > Further, since printf (the utility) is really just converting text > strings from one format to another, there's really no reason that there > needs to be any limit at all - there's no particular reason that integers > thousands of digits long couldn't be handled. The standard does say that > if overflow occurs, an error message, and non-zero exit status, must > occur, but it doesn't ever say that overflow must occur. XCU 1.1.2.1 implies there must be an upper limit, since signed long in ISO C is a fixed-width type. However, I suppose an implementation could get around that by claiming printf works as if implemented in a C programming environment where the number of hex digits in LONG_MAX is greater than ARG_MAX, and thus a too-large value could never be passed to (an external) printf. > Second question - if overflow does occur (at whatever point) what is the > value that must be printed (in addition to the error message) from a > numeric conversion. > [...] > what the standard says is: > > If an argument operand cannot be completely converted into an internal > value appropriate to the corresponding conversion specification, a > diagnostic message shall be written to standard error and the utility > shall not exit with a zero exit status, but shall continue processing > any remaining operands and shall write the value accumulated at the > time the error was detected to standard output. > > The question is, what is "the value accumulated at the time the error was > detected". That would obviously depend on internal implementation details. In particular, digits could be processed left-to-right or right-to-left, so the unused digits could be from either end. > What zsh does is: > > zsh $ printf '%d\n' 0xffffc00000000000 > zsh: number truncated after 15 digits: ffffc00000000000 > 1152917106560335872 > > which makes some sense to me, I had been thinking this might be the > correct value, before I started testing to see what was produced. > That is, after the first 15 hex digits are consumed, that is the value > (0xffffc0000000000 in decimal) and then when an attempt is made to > add one more zero, we detect the overflow, and so the value that had > been accumulated when the overflow was detected was 1152917106560335872 > (when printed via %d). > > The value "everybody" else prints, 9223372036854775807, is simply 2^63-1 > (the max possible value) which most likely was never actually encountered > during the conversion, but is just what strtoll() returns as its value. I think that's allowed, via the usual "as if" rule. An implementor could claim that printf is implemented as if the "accumulated" value is simply incremented until converting it to a hex string produces the same digits as were supplied, or the maximum representable accumulated value is reached. -- Geoff Clare <g.cl...@opengroup.org> The Open Group, Apex Plaza, Forbury Road, Reading, RG1 1AX, England