Shouldn't the return be of type size_t instead? Because the size of objects in C is of this type, including the string passed to printf.
3 Answers
Why printf returns an int in C?
Shouldn't be of typesize_tinstead?
It could have been, but certainly an early design decision was to accommodate a return value of the negative EOF to indicate error.
size_t was something of an afterthought in early design choices. Many functions used int where size_t is used now in those pre-standard days.
fprintf() has an environmental limit "The number of characters that can be produced by any single conversion shall be at least 4095.", so any print that is attempting long output may run into that limit before INT_MAX/SIZE_MAX concerns.
8 Comments
int is simple.printf, for one reason, or another, doesn't comply to the standard? Because it uses an int to hold the number of characters.printf() an extraordinary common function in those pre-standard days (1970s - 1989), became the target to match once the standard 1989 was created. That creation did not attempt to break existing practice where it could avoid it. printf() complies to the standard because it is the standard on which C89 was based.char buff[N]; size_t sz = sizeof(buff); int n = snprintf(buff, sz, "..."); if (n < sz) ... gives rise to warnings about comparing signed and unsigned.n < 0 indicates an encoding error. if (n < 0 || (uintmax_t) n >= sz) error(); should certainly cover all platforms.You're largely right - actually printf should return a larger type, since it's theoretically possible to output many more bytes than the size of the largest object that can fit in memory, e.g. printf("%s%s", largest_string, largest_string) or even more trivial examples using field widths/precisions.
The reason is just a historical mistake that we're stuck with. It's particularly bad with snprintf, which is artificially limited to INT_MAX and is forced to return an error if you attempt to create a longer string with it.
4 Comments
(T)-1, where T is an unsigned type, as the error indication. Note that this works conveniently with snprintf where retval>=n is the error condition (truncation or error causing negative return) that you need to check for anyway.(T)-1 is a good idea. int retval = snprintf(... size_t n, ... and retval>=n works well aside from fantasy platforms where INT_MAX > SIZE_MAX for the retval>=n is a signed compare. error = retval < 0 || retval >= n; always works.snprintf actually returned size_t or some unsigned type.
printfis unlikely to exceed 32k, let alone 2G.printfreturn value can be negative. Thesize_ttype is unsigned.printfwas designed, there was nosize_tand people usedints. Changing it tosize_twould break some old code, so they can’t do that; if they were to designprintffrom scratch now they probably would usesize_t.size_torssize_t, but it really makes no difference for any real world example that I can think of.size_tisn't good cause you need a way to signal errors, and you can't use 0 for that because 0 is kind of a legitimate output count forprintf. I think I'd use ` ssize_t/ptrdiff_t/long` if I was doing my ownprintf.