Home > Back-end >  Why fseek has "long int offset" instead of "long long int offset"?
Why fseek has "long int offset" instead of "long long int offset"?

Time:02-08

C2x, 7.21.9.2 The fseek function:

Synopsis

#include <stdio.h>
int fseek(FILE *stream, long int offset, int whence);

Why fseek has long int offset instead of long long int offset?

It seems that on operating systems with data model LLP64 or ILP32 (e.g. Microsoft Windows) the 2147483647 (2.1 GB approx.) may be unsufficient.

Note: POSIX's lseek has off_t offset, where off_t "isn't very rigorously defined".

CodePudding user response:

The C Standard was formalized in 1990 when most hard drives were smaller than 2 GB. The prototype for fseek() was already in broad use with a long type offset and 32 bits seemed large enough for all purposes, especially since the corresponding system call used the same API already. They did add fgetpos() and fsetpos() for exotic file systems where a simple long offset did not carry all the necessary information for seeking, but kept the fpos_t type opaque.

After a few years, when 64 bit offsets became necessary, many operating systems added 64-bit versions of the system calls and POSIX introduced fseeko() and ftello() to provide a high level interface for larger offsets. These extensions are not necessary anymore for 64-bit versions of common operating systems (linux, OS/X) but Microsoft decided to keep it's long, or more precisely LONG, type at 32-bits, solidifying this issue and other ones too such as size_t being larger than unsigned long. This very unfortunate decision plagues C developers on Win64 platforms ever since and forces them to use non portable APIs for large files.

Changing fseek and ftell prototypes would create more problems with existing software as it would break compatibility, so it will not happen.

Some other historical shortcomings are even more surprising, such as the prototype for fgets():

char *fgets(char * restrict s, int n, FILE * restrict stream);

Why did they use int instead of size_t is a mystery: back in 1990, int and size_t had the same size on most platforms and it did not make sense to pass a negative value anyway. Again, this inconsistent API is here to stay.

  •  Tags:  
  • Related