C2x, 7.21.9.2 fseek 函数:
概要
#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)可能是不够的。
C2x, 7.21.9.2 fseek 函数:
概要
#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。for 的原型fseek()
已经被广泛使用,带有long
类型偏移,32 位似乎足以满足所有目的,特别是因为相应的系统调用已经使用了相同的 API。他们确实为奇异的文件系统添加了fgetpos()
和fsetpos()
,其中一个简单的长偏移量没有携带所有必要的信息来寻找,但保持fpos_t
类型不透明。
几年后,当 64 位偏移量变得必要时,许多操作系统添加了 64 位版本的系统调用并引入了 POSIXfseeko()
并ftello()
为更大的偏移量提供高级接口。这些扩展对于 64 位版本的通用操作系统(linux、OS/X)不再是必需的,但微软决定将其保留为 32 位long
,或者更准确地说LONG
,将其类型保留为 32 位,从而巩固了这个问题以及其他问题,例如size_t
更大比unsigned long
。从那时起,这个非常不幸的决定一直困扰着 Win64 平台上的 C 开发人员,并迫使他们对大文件使用不可移植的 API。
更改fseek
和ftell
原型会为现有软件带来更多问题,因为它会破坏兼容性,因此不会发生。
其他一些历史缺陷更令人惊讶,例如 的原型fgets
:
char *fgets(char * restrict s, int n, FILE * restrict stream);
他们为什么使用int
而不是size_t
是一个谜:早在 1990 年,int
在size_t
大多数平台上都有相同的大小,无论如何传递负值是没有意义的。同样,这种不一致的 API 将继续存在。