Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does fgets accept an int instead of a size_t?

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?

like image 382
user2064000 Avatar asked Aug 02 '16 11:08

user2064000


People also ask

Why we use fgets instead of gets?

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().

Why does Size_t exist?

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.

Is Size_t signed?

gcc actually defines size_t as a signed integer type.

Can a Size_t be negative?

The size_t data type is never negative.


1 Answers

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

  • Going from K&R to Ansi C - Dr.Dobb's - 1989:

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.

like image 191
Christophe Avatar answered Sep 21 '22 15:09

Christophe