Pav*_*kin 6 c fseek language-lawyer long-integer c-standard-library
C2x,7.21.9.2 fseek 函数:
概要
Run Code Online (Sandbox Code Playgroud)#include <stdio.h> int fseek(FILE *stream, long int offset, int whence);
为什么fseek有long int offset而不是long long int offset?
似乎在具有数据模型LLP64 或 ILP32 的操作系统(例如 Microsoft Windows)上2147483647(2 GB)可能不够。
C 标准于 1990 年正式制定,当时大多数硬盘驱动器都小于 2 GB。的原型fseek()已经被广泛使用,带有long类型偏移量,32 位似乎足够大,足以满足所有目的,特别是因为相应的系统调用已经使用了相同的 API。他们确实为外来文件系统添加了fgetpos()和fsetpos(),其中简单的长偏移量不携带查找所需的所有信息,但保持类型fpos_t不透明。
几年后,当 64 位偏移量变得必要时,许多操作系统添加了 64 位版本的系统调用,并引入了 POSIX fseeko(),并ftello()为更大的偏移量提供高级接口。对于 64 位版本的常见操作系统(linux、OS/X)来说,这些扩展不再是必需的,但 Microsoft 决定将其(long或更准确地说LONG,是 32 位类型)保留下来,从而解决了这个问题以及其他问题,例如size_t变得更大比unsigned long。这个非常不幸的决定从此困扰着 Win64 平台上的 C 开发人员,迫使他们对大文件使用不可移植的 API。
更改fseek和ftell原型会给现有软件带来更多问题,因为它会破坏兼容性,所以它不会发生。
其他一些历史缺陷甚至更令人惊讶,例如 的原型fgets:
char *fgets(char * restrict s, int n, FILE * restrict stream);
Run Code Online (Sandbox Code Playgroud)
他们为什么使用int而不是size_t一个谜:早在 1990 年,int并且size_t在大多数平台上具有相同的大小,无论如何传递负值是没有意义的。同样,这种不一致的 API 将继续存在。