Ahm*_*sud 11
long int应该是至少32位,但C99标准不限制为32位.C99标准确实提供了诸如int16_t&int32_tetc之类的便利类型,它们映射到目标平台的正确位大小.
ftell()并且fseek()在绝大多数32位架构系统上限制为32位(包括符号位).所以当有大量文件支持时,你会遇到这个2GB的问题.
POSIX.1-2001和SysV功能fseek和ftell是fseeko和ftello,因为他们使用off_t作为偏移参数.
你需要-D_FILE_OFFSET_BITS=64 在包含stdio.h之前用某个地方定义编译或定义它,以确保它off_t是64位.
请阅读cert.org安全编码指南,了解相关信息.
C99说long int必须至少 32位,并不是说它不能更大
在x86_64架构上尝试以下方法:
#include <stdio.h>
int main(int argc, char *argv[]) {
FILE *fp;
fp = fopen( "test.out", "w");
if ( !fp )
return -1;
fseek(fp, (1L << 34), SEEK_SET);
fprintf(fp, "\nhello world\n");
fclose(fp);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
请注意,这1L只是一个long,这将产生一个17GB的文件,并坚持"\nhello world\n"到它的结尾.您可以通过简单地使用tail -n1 test.out或明确使用来验证:
dd if = test.out skip = $((1 << 25))
请注意,dd通常使用块大小,(1 << 9)因此 34 - 9 = 25将转储出来'\nhello world\n'
至少在32位操作系统上,ftell()它会溢出或出错,或者仅会遇到未定义的行为。
为了解决这个问题,您可能想使用off_t ftello(FILE *stream);和#define _FILE_OFFSET_BITS 64。
逐字记录来自man ftello:
fseeko()和ftello()函数分别与fseek(3)和ftell(3)相同(请参阅fseek(3)),除了fseeko()的offset参数和ftello()的返回值是输入off_t而不是long。
在许多架构上,off_t和long都是32位类型,但是使用
Run Code Online (Sandbox Code Playgroud)#define _FILE_OFFSET_BITS 64将把off_t变成64位类型。
更新:
根据IEEE Std 1003.1,2013版 ftell()应在以下情况下返回-1并设置errno为EOVERFLOW:
人流
对于ftell(),当前文件偏移不能在long类型的对象中正确表示。