Functions such as strcpy()
, malloc()
, strlen()
and various others accept their arguments or return values as a size_t
instead of a int
or an unsigned int
for obvious reasons.
Some file functions such as fread()
and fwrite()
use size_t
as well. By extension, it would be expected that char* fgets (char *str, int num, FILE *stream)
should use a size_t
and not an int
as argument for its buffer size.
However, fgets()
uses an int
. Is there any objective explanation why?
By specifying stdin as the stream, fgets() can be used to simulate the behavior of gets() , as shown in lines 6-10 of Figure 1. Unlike gets(), the fgets() function retains the newline character, meaning that the function cannot be used as a direct replacement for gets().
The type-aliases (like size_t ) is to make code more legible and is more to show intent. Using size_t you say that "this is a size", so it's more for the programmers and less for the need of the compiler.
gcc actually defines size_t as a signed integer type.
The size_t data type is never negative.
The original K&R defined fgets()
on p.155 with an int
argument. The code presented in the book would have worked
with an unsigned int
as well (it uses a >0
, but the loop is written so to never go below zero).
size_t
got introduced later, in C89 (ANSI C), as the type of sizeof()
. As this feature was specifically introduced for harmonizing memory allocation, memory
management functions and string functions were updated accordingly. But file I/O wasn't: the only file functions that used size_t
in C89 are those new ones
introduced by C89 and did not exist in K&R such as for example fread()
/fwrite()
. Yes, K&R didn't have these functions
and relied for bloc operations only on (non portable) unix read/write functions using file descriptors.
It shall be noted that the POSIX standard, which has harmonized the unix functions, was developed in parallel to
the ANSI C standard and issued late 1988. This standard has harmonized many unix functions to use size_t
so that read()
/write()
nowadays
are defined with size_t
. But for the C standard library functions such as fgets()
, POSIX gives precedence to the C standard
(wording of the current version of the standard):
The functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional.
So in POSIX also, ironically, fgets()
still inherited from its historical K&R int
.
Edit: additional reading
stdio.h: This header defines and prototypes most of the functions listed in Chapter 7 of K&R. Few, if any, changes were made in the definitions found in K&R but several new functions have been added.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With