C ++使用streamoff
类型表示(文件)流中的偏移量,并在[stream.types]中定义如下:
using streamoff = implementation-defined ;
streamoff类型是已签名的基本整数类型之一的同义词,该基本整数类型的大小足以表示操作系统的最大可能文件大小。 287)
287)通常很长很长。
这很有意义,因为它允许在大文件中查找(与使用long
(可能只有32位宽)相反)。
[filebuf.virtuals]定义了basic_filebuf
的在文件中进行搜索的功能,如下所示:
pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;
off_type
等效于streamoff
,请参见[iostreams.limits.pos]。但是,该标准随后继续说明了该功能的作用。最后一句话让我很生气,这需要调用fseek
:
效果:让
width
代表a_codecvt.encoding()
。如果为is_open() == false
或off != 0 && width <= 0
,则定位操作失败。否则,如果为way != basic_ios::cur
或off != 0
,并且 如果输出了最后一个操作,则更新输出序列并写入所有未移位序列。 接下来,寻找新位置:如果width > 0
,请致电fseek(file, width * off, whence)
,否则 致电fseek(file, 0, whence)
。
fseek
接受一个long
参数。如果off_type
和streamoff
被定义为long long
(如标准所建议),则在调用long
时可能导致向下转换为fseek(file, width * off, whence)
(导致可能难以诊断错误)。这使人们质疑首先引入streamoff
类型的整个理由。
这是故意的还是标准的缺陷?
答案 0 :(得分:5)
我认为您从中得出的结论是C ++流与fseek
之间的不匹配会导致运行时错误,这是不正确的。情况似乎是:
在long
是64位的系统上,streamoff
被定义为long
,并且seekoff
函数调用fseek
。
在long
是32位但操作系统支持64位文件偏移量的系统上,streamoff
被定义为long long
,并且seekoff
调用一个称为fseeko
或fseeko64
接受64位偏移。
以下是我的Linux系统上seekoff
的定义的摘录:
#ifdef _GLIBCXX_USE_LFS
if (!fseeko64(_M_file, __off, __whence))
__ret = std::streampos(ftello64(_M_file));
#else
if (!fseek(_M_file, __off, __whence))
__ret = std::streampos(std::ftell(_M_file));
#endif
LFS代表Large File Support。
结论:尽管标准提出了streamoff
的定义,表面上与seekoff
调用fseek
的要求相矛盾,但库设计人员理解他们必须调用{{1}的变体}接受操作系统支持的所有偏移量。