为什么 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);
为什么 fseek
有 long 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。
更改 fseek
和 ftell
原型会给现有软件带来更多问题,因为它会破坏兼容性,因此不会发生。
其他一些历史遗漏更令人吃惊,例如fgets
的原型:
char *fgets(char * restrict s, int n, FILE * restrict stream);
为什么他们使用 int
而不是 size_t
是一个谜:早在 1990 年,int
和 size_t
在大多数平台上的大小都相同,而且确实如此无论如何传递负值是没有意义的。同样,这种不一致的 API 将继续存在。
C2x, 7.21.9.2 fseek 函数:
Synopsis
#include <stdio.h> int fseek(FILE *stream, long int offset, int whence);
为什么 fseek
有 long 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。
更改 fseek
和 ftell
原型会给现有软件带来更多问题,因为它会破坏兼容性,因此不会发生。
其他一些历史遗漏更令人吃惊,例如fgets
的原型:
char *fgets(char * restrict s, int n, FILE * restrict stream);
为什么他们使用 int
而不是 size_t
是一个谜:早在 1990 年,int
和 size_t
在大多数平台上的大小都相同,而且确实如此无论如何传递负值是没有意义的。同样,这种不一致的 API 将继续存在。