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

Pav*_*kin 6 c fseek language-lawyer long-integer c-standard-library

C2x,7.21.9.2 fseek 函数:

概要

#include <stdio.h>
int fseek(FILE *stream, long int offset, int whence);
Run Code Online (Sandbox Code Playgroud)

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

似乎在具有数据模型LLP64 或 ILP32 的操作系统(例如 Microsoft Windows)上2147483647(2 GB)可能不够。

注意:POSIX 的lseekoff_t offset,其中off_t没有非常严格的定义”。

chq*_*lie 4

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。

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

其他一些历史缺陷甚至更令人惊讶,例如 的原型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 将继续存在。

  • “从此困扰 Win64 平台上的 C 开发人员,迫使他们对大文件使用不可移植的 API。” --&gt; 我怀疑这是一个故意的[选择](https://en.wikipedia.org/wiki/Embrace,_extend,_and_Extend)。 (2认同)