为什么 ftell 的 return 类型不是 fpos_t?
Why is the return type for ftell not fpos_t?
根据 C99,ftell
的原型是:
long int ftell(FILE *stream);
根据我的理解,应该是以下内容:
fpos_t ftell(FILE *stream);
这是为什么?
来自§7.19.1-2
fpos_t
which is an object type other than an array type capable of recording all the information needed to specify uniquely every position within a file.
我明白 fpos_t
应该用来记录文件中的位置。因此 ftell
文件中的哪个 returns 位置应该属于该类型。相反,它是:
signed
- 类型
long
可能太小或太大而无法在某些体系结构上访问文件。
来自 fgetpos()/fsetpos()
的联机帮助页:
On some non-UNIX systems, an fpos_t object may be a complex object and these routines may be the only way to portably reposition a text stream.
而 ftell()
需要 return 文件指针在文件中的偏移量。这些是完全不同的接口。
注意 fpos_t
是
[...] a complete object type other than an array type capable of recording all the information needed to specify uniquely every position within a file.
所以它甚至可以是一个结构,除了调用 fsetpos
之外完全不能用于任何其他用途!
另一方面,ftell
的 return 值是一个标量,保证可用于告知二进制文件中的确切字节位置:
For a binary stream, the value is the number of characters from the beginning of the file.
除此之外,原因是向后兼容性。 ftell
在 C89 中首次亮相,也许当时的期望是 long
可以足够快地扩展以包含所有文件大小,但如今情况并非总是如此。不幸的是,无法更改由 ftell
编辑的 return 类型,但现在更改它为时已晚 - 即使那些支持更大文件的平台现在也有另一个名称的函数,例如 ftello
.
需要签名,因为函数 returns -1
出错。
最可能的用途是允许错误 return 值为负数。它与 printf
函数族相同,即 return ssize_t
而不是 size_t
,恰好是 size_t
的 signed
版本.
这些技巧中的第一个发生在 getchar()
上,return 是 int
而不是 char
,以允许值 returned on文件结束条件 (EOF
) 通常是一个负值,以与整组可能的 returned 字符(在 0
到 255
范围内,所有正整数)
为什么不定义相同类型的签名扩展以允许 -1
?其实不知道:)
历史原因。
fseek
和 ftell
是非常古老的函数,早于 C 标准化。他们假设 long
足够大以表示任何文件中的一个位置——这个假设在当时可能是有效的。 long
至少是 32 位,并且 显然 单个文件不能超过 2 GB(甚至 1.21 gigabytes)。
当第一个 C 标准发布时(ANSI C,1989),很明显这个假设不再有效,但是改变 fseek
和 ftell
的定义会破坏了现有的代码。此外,仍然没有比 long
宽的整数类型(long long
直到 C99 才被引入)。
ANSI C 委员会决定 fseek
和 ftell
仍然有用,但他们引入了新的文件定位函数 fsetpos
和 fgetpos
。这些函数使用不透明的非数字类型 fpos_t
而不是 long
,这使得它们比 fseek
和 ftell
更灵活也更不灵活。一个实现可以定义 fpos_t
因此它可以表示任何可能的文件偏移量——但由于它是非数字类型,fsetpos
和 fgetpos
不提供 SEEK_SET
/ SEEK_CUR
/ SEEK_END
特征。例如,无法使用 fsetpos
将文件定位到末尾。
其中一些在 ANSI C Rationale, section 4.9.9 中得到解决:
Given these restrictions, the Committee still felt that this function [fseek
] has enough utility, and is used in sufficient existing code, to warrant its retention in the Standard. fgetpos
and fsetpos
have been added to deal with files which are too large to handle with fseek
and ftell
.
如果今天从头开始定义它,可能会有一对函数涵盖当前四个函数的所有功能,很可能使用需要足够大的 typedef
ed 整数类型表示任何可能的文件偏移量。 (对于当前的系统,64 位可能就足够了,但在大型系统上不久之后看到 8 艾字节的文件我不会感到惊讶)。
根据 C99,ftell
的原型是:
long int ftell(FILE *stream);
根据我的理解,应该是以下内容:
fpos_t ftell(FILE *stream);
这是为什么?
来自§7.19.1-2
fpos_t
which is an object type other than an array type capable of recording all the information needed to specify uniquely every position within a file.
我明白 fpos_t
应该用来记录文件中的位置。因此 ftell
文件中的哪个 returns 位置应该属于该类型。相反,它是:
signed
- 类型
long
可能太小或太大而无法在某些体系结构上访问文件。
来自 fgetpos()/fsetpos()
的联机帮助页:
On some non-UNIX systems, an fpos_t object may be a complex object and these routines may be the only way to portably reposition a text stream.
而 ftell()
需要 return 文件指针在文件中的偏移量。这些是完全不同的接口。
注意 fpos_t
是
[...] a complete object type other than an array type capable of recording all the information needed to specify uniquely every position within a file.
所以它甚至可以是一个结构,除了调用 fsetpos
之外完全不能用于任何其他用途!
另一方面,ftell
的 return 值是一个标量,保证可用于告知二进制文件中的确切字节位置:
For a binary stream, the value is the number of characters from the beginning of the file.
除此之外,原因是向后兼容性。 ftell
在 C89 中首次亮相,也许当时的期望是 long
可以足够快地扩展以包含所有文件大小,但如今情况并非总是如此。不幸的是,无法更改由 ftell
编辑的 return 类型,但现在更改它为时已晚 - 即使那些支持更大文件的平台现在也有另一个名称的函数,例如 ftello
.
需要签名,因为函数 returns -1
出错。
最可能的用途是允许错误 return 值为负数。它与 printf
函数族相同,即 return ssize_t
而不是 size_t
,恰好是 size_t
的 signed
版本.
这些技巧中的第一个发生在 getchar()
上,return 是 int
而不是 char
,以允许值 returned on文件结束条件 (EOF
) 通常是一个负值,以与整组可能的 returned 字符(在 0
到 255
范围内,所有正整数)
为什么不定义相同类型的签名扩展以允许 -1
?其实不知道:)
历史原因。
fseek
和 ftell
是非常古老的函数,早于 C 标准化。他们假设 long
足够大以表示任何文件中的一个位置——这个假设在当时可能是有效的。 long
至少是 32 位,并且 显然 单个文件不能超过 2 GB(甚至 1.21 gigabytes)。
当第一个 C 标准发布时(ANSI C,1989),很明显这个假设不再有效,但是改变 fseek
和 ftell
的定义会破坏了现有的代码。此外,仍然没有比 long
宽的整数类型(long long
直到 C99 才被引入)。
ANSI C 委员会决定 fseek
和 ftell
仍然有用,但他们引入了新的文件定位函数 fsetpos
和 fgetpos
。这些函数使用不透明的非数字类型 fpos_t
而不是 long
,这使得它们比 fseek
和 ftell
更灵活也更不灵活。一个实现可以定义 fpos_t
因此它可以表示任何可能的文件偏移量——但由于它是非数字类型,fsetpos
和 fgetpos
不提供 SEEK_SET
/ SEEK_CUR
/ SEEK_END
特征。例如,无法使用 fsetpos
将文件定位到末尾。
其中一些在 ANSI C Rationale, section 4.9.9 中得到解决:
Given these restrictions, the Committee still felt that this function [
fseek
] has enough utility, and is used in sufficient existing code, to warrant its retention in the Standard.fgetpos
andfsetpos
have been added to deal with files which are too large to handle withfseek
andftell
.
如果今天从头开始定义它,可能会有一对函数涵盖当前四个函数的所有功能,很可能使用需要足够大的 typedef
ed 整数类型表示任何可能的文件偏移量。 (对于当前的系统,64 位可能就足够了,但在大型系统上不久之后看到 8 艾字节的文件我不会感到惊讶)。