C2x, 7.21.9.2 The fseek function:
Synopsis
#include <stdio.h> int fseek(FILE *stream, long int offset, int whence);
Why does fseek have 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 GB) may be insufficient.
Note: POSIX's lseek has off_t offset, where off_t "isn't very rigorously defined".
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 alongtype offset and 32 bits seemed large enough for all purposes, especially since the corresponding system call used the same API already. They did addfgetpos()andfsetpos()for exotic file systems where a simple long offset did not carry all the necessary information for seeking, but kept thefpos_ttype 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()andftello()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'slong, or more preciselyLONG, type at 32-bits, solidifying this issue and other ones too such assize_tbeing larger thanunsigned 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
fseekandftellprototypes 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:Why did they use
intinstead ofsize_tis a mystery: back in 1990,intandsize_thad 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.