Thread: *printf and zero size
Tom, did you implement this functionality in *printf? The size may be given as zero to find out how many characters areneeded; in this case, the str argument is ignored. Sprintf()andvsprintf() effectively assume an infinite size. Looking at the code it doesn't seem supported. Should it be added to the limitations comment section? -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001+ If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania19073
Bruce Momjian <pgman@candle.pha.pa.us> writes: > Tom, did you implement this functionality in *printf? > The size may be given as zero to find out how many characters are > needed; in this case, the str argument is ignored. Sprintf() and > vsprintf() effectively assume an infinite size. Where do you read that? The SUS says the opposite: If the value of n is zero on a call to snprintf(), an unspecifiedvalue less than 1 is returned. and that's what our code implements. regards, tom lane
Tom Lane wrote: > Bruce Momjian <pgman@candle.pha.pa.us> writes: > > Tom, did you implement this functionality in *printf? > > The size may be given as zero to find out how many characters are > > needed; in this case, the str argument is ignored. Sprintf() and > > vsprintf() effectively assume an infinite size. > > Where do you read that? The SUS says the opposite: > > If the value of n is zero on a call to snprintf(), an unspecified > value less than 1 is returned. > > and that's what our code implements. I got it from the BSD/OS manual page, and in the NetBSD manual page I see: If size is zero, nothing is written and str may be a NULL pointer. and: Upon successful completion snprintf() and vsnprintf() return the numberof characters that would have been written to a sufficientlysized str,excluding the terminating NUL character. but it seems this is some BSD'ism that we don't need to support if the standard doesn't say so. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001+ If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania19073
Bruce Momjian <pgman@candle.pha.pa.us> writes: > Upon successful completion snprintf() and vsnprintf() return the number > of characters that would have been written to a sufficiently sized str, > excluding the terminating NUL character. > but it seems this is some BSD'ism that we don't need to support if the > standard doesn't say so. Yeah, that is a BSD-ism. You have a point though, we ought to document which return convention the code follows. I'll add something. regards, tom lane
Kurt Roeckx <kurt@roeckx.be> writes: > Concerning the return value of snprintf(), the SUSv2 and the C99 stan- > dard contradict each other: Is that where the problem comes from? Anyway, I've added some text to snprintf.c explaining what we do. Since the calling code has to be prepared to handle either result convention, I see no need to do anything except what's easiest to implement, which in this case is the SUS behavior. (There's also a consistency issue, which is that fprintf is supposed to return the number of bytes actually transmitted, not the number it would have sent in the absence of error.) regards, tom lane * 5. Space and '#' flags are not implemented. + * + * + * The result values of these functions are not the same across different + * platforms. This implementation is compatible with the Single Unix Spec: + * + * 1. -1 is returned only if processing is abandoned due to an invalid + * parameter, such as incorrect format string. (Although not required by + * the spec, this happens only when no characters have yet been transmitted + * to the destination.) + * + * 2. For snprintf and sprintf, 0 is returned if str == NULL or count == 0; + * no data has been stored. + * + * 3. Otherwise, the number of bytes actually transmitted to the destination + * is returned (excluding the trailing '\0' for snprintf and sprintf). + * + * For snprintf with nonzero count, the result cannot be more than count-1 + * (a trailing '\0' is always stored); it is not possible to distinguish + * buffer overrun from exact fit. This is unlike some implementations that + * return the number of bytes that would have been needed for the complete + * result string. */
On Mon, Dec 05, 2005 at 04:35:31PM -0500, Bruce Momjian wrote: > > but it seems this is some BSD'ism that we don't need to support if the > standard doesn't say so. I think the Linux manpage is more informative about this: The functions snprintf and vsnprintf do not write more than size bytes (including the trailing '\0'). If theoutput was truncated due to this limit then the return value is the number of characters (not includingthe trailing '\0') which would have been written to the final string if enough space had been available. Thus,a return value of size or more means that the output was truncated. (See also below under NOTES.) Ifan output error is encountered, a negative value is returned. [...] NOTES The glibc implementation of the functions snprintf() and vsnprintf() conforms to the C99 standard, i.e.,behaves as described above, since glibc version 2.1. Until glibc 2.0.6 they would return -1 when the out- put was truncated. [...] Concerning the return value of snprintf(), the SUSv2 and the C99 stan- dard contradict each other: when snprintf()is called with size=0 then SUSv2 stipulates an unspecified return value less than 1, while C99 allowsstr to be NULL in this case, and gives the return value (as always) as the number of characters thatwould have been written in case the output string has been large enough. Kurt