fseek - 无法跳过大量字节?

fseek - fails skipping a large amount of bytes?

我试图在使用 fread 读取下一个字节之前跳过大量字节。 当尺寸较小时 #define size 6404168 - 它有效:

long int x = ((long int)size)*sizeof(int);
fseek(fincache, x, SEEK_CUR);

当大小很大时#define size 649218227,它不会:(下一个fread读取垃圾,无法真正理解它从哪个偏移量读取。

使用 fread 作为变通方法在这两种情况下都有效,但它真的很慢:

temp = (int *) calloc(size, sizeof(int));
fread(temp,1, size*sizeof(int), fincache);
free(temp);

fseekoffset 参数必须是 long,而不是 long long。所以 x 必须适合 long,否则不要使用 fseek

fseek 的输入指南:

http://www.tutorialspoint.com/c_standard_library/c_function_fseek.htm

int fseek(FILE *stream, long int offset, int whence)

offset − This is the number of bytes to offset from whence.

您通过将 long long(其值大于 Long int 的最大值)传递给 fseek 而不是所需的 long.

来调用未定义的行为

众所周知,UB可以做任何事情,包括不工作。

由于您的平台的 int 很可能是 32 位的,将 649,218,227 乘以 sizeof(int) 得到的数字超过了 INT_MAXLONG_MAX,它们都是 2 **32 位平台上的 31-1。由于 fseek 接受 long int,由此产生的溢出导致您的程序打印垃圾。

您应该查阅编译器的文档,了解它是否提供了 64 位搜索的扩展。例如,在 POSIX 系统上,您可以使用 fseeko,它接受 off_t.

类型的偏移量

注意不要在调用64位查找函数之前引入溢出。仔细的代码可能如下所示:

off_t offset = (off_t) size * (off_t) sizeof(int);
fseeko(fincache, offset, SEEK_CUR);

假设 sizoef(int)4 并且您使用的是 32 位系统(其中 sizeof(long) 是 4),

所以 649218227*4 会溢出 long 可以容纳的内容。有符号整数溢出是未定义的行为。所以你它适用于较小的值(小于 LONG_MAX)。

您可以使用循环代替 fseek() 必要的字节。

long x;
intmax_t len = size;

for(;len>0;){    
   x = (long) (len>LONG_MAX?LONG_MAX:len);
   fseek(fincache, x, SEEK_CUR);
   len = len-x;
}

试试这个,这么大的数字你可能要读出来

 size_t toseek = 6404168;
 //change the number to increase it
 while(toseek>0)
 {
    char buffer[4096];
    size_t toread = min(sizeof(buffer), toseek);
    size_t read = fread(buffer, 1, toread, stdin);
    toseek = toseek - read;
 }