The venerable snprintf() function...
int snprintf( char *restrict buffer, size_t bufsz, const char *restrict format, ... );
How does it make sense for the buffer size to be size_t, but for the return type to be only an int?
If snprintf() is supposed to be able to print more than INT_MAX characters into the buffer, surely it must return an ssize_t or a size_t with (size_t) - 1 indicating an error, right?
And if it is not supposed to be able to print more than INT_MAX characters, why is bufsz a size_t rather than, say, an unsigned or an int? Or - is it at least officially constrained to hold values no larger than INT_MAX?
printf predates the existence of size_t and similar "portable" types -- when printf was first standardized, the result of a sizeof was an int.
This is also the reason why the argument in the printf argument list read for a * width or precision in the format is an int rather than a size_t.
snprintf is more recent, so the size it takes as an argument was defined to be a size_t, but the return value was kept as an int to make it the same as printf and sprintf.
Note that you can print more than INT_MAX characters with these functions, but if you do, the return value is unspecified. On most platforms, an int and a size_t will both be returned in the same way (in the primary return value register), it is just that a size_t value may be out of range for an int. So many platforms actually return a size_t (or ssize_t) from all of these routines and things being out of range will generally work out ok, even though the standard does not require it.
The discrepancy between size and return has been discussed in the standards group in the thread https://www.austingroupbugs.net/view.php?id=761. Here is the conclusion posted at the end of that thread:
Further research has shown that the behavior when the return value would overflow int was clarified by WG14 in C99 by adding it into the list of undefined behaviors in Annex J. It was updated in C11 to the following text:
"J.2 Undefined behavior The behavior is undefined in the following circumstances: [skip] — The number of characters or wide characters transmitted by a formatted output function (or written to an array, or that would have been written to an array) is greater than INT_MAX (7.21.6.1, 7.29.2.1)."
Please note that this description does not mention the size argument of snprintf or the size of the buffer.
If
snprintf()is supposed to be able to print more thanINT_MAXcharacters into the buffer, surely it must return anssize_tor asize_twith(size_t) - 1indicating an error, right?
Not quite.
C also has an Environmental limit for fprintf() and friends.
The number of characters that can be produced by any single conversion shall be at least 4095." C17dr § 7.21.6.1 15
Anything over 4095 per % risks portability and so int, even at 16-bit (INT_MAX = 32767), suffices for most purposes for portable code.
Note: the ssize_t is not part of the C spec.