为什么 fseek 有 "long int offset" 而不是 "long long int offset"?

Why does fseek have "long int offset" instead of "long long int offset"?

C2x, 7.21.9.2 fseek 函数:

Synopsis

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

为什么 fseeklong int offset 而不是 long long int offset

似乎在数据模型为 LLP64 or ILP32 的操作系统上(例如 Microsoft Windows),2147483647 (2 GB) 可能不足。

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

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 开发人员,并迫使他们对大文件使用不可移植的 APIs。

更改 fseekftell 原型会给现有软件带来更多问题,因为它会破坏兼容性,因此不会发生。

其他一些历史遗漏更令人吃惊,例如fgets的原型:

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

为什么他们使用 int 而不是 size_t 是一个谜:早在 1990 年,intsize_t 在大多数平台上的大小都相同,而且确实如此无论如何传递负值是没有意义的。同样,这种不一致的 API 将继续存在。