fseek和SEEK_END的行为

时间:2014-12-18 15:11:21

标签: c fseek

如果我有一个文本文件,其中包含以二进制文件打开的以下内容

1234567890

这样的电话:

fseek(fp, 5L, SEEK_SET);

当我调用(char)fgetc(fp)时给我6,因为我从字节0偏移了5个字节(不是从1开始而是从2开始)

但如果我这样做:

fseek(fp, -3L, SEEK_END);
当我打电话给(char)fgetc(fp)时,

给我8而不是7。

为什么呢?与SEEK_END一样,偏移量不会从最后一个字节后的前一个字节开始。

3 个答案:

答案 0 :(得分:7)

SEEK_END从文件的一个过去的最后一个字节进行搜索:

1234567890   <--- bytes from the file
0123456789A  <--- SEEK_SET-relative position
A9876543210  <--- SEEK_END-relative position (absolute value)
          ^
          This is the (0, SEEK_END) byte

考虑到这一点,文件的最后一个字节是在(-1, SEEK_END)找到的字节,因此(-3, SEEK_END)字节是8

请注意,这与C通常处理此类事物的方式一致。例如,指向内存块末尾的指针通常指向该块的最后一个字节的一个。

这也有一个很好的功能,你可以通过调用fseek(SEEK_END)ftell()来获取文件的大小。无需添加或减去1

fseek()的手册页对此问题有点含糊不清,但与包含相同问题的man lseek进行比较:

  

如果是SEEK_END,则文件偏移量应设置为文件大小加偏移量。

在您的示例中,文件的大小为10,偏移量为-3,因此最终位置为10-3 = 7。在偏移7中有一个8

答案 1 :(得分:0)

我认为是因为文件的最后一个字符是'\n''\0'或类似的东西。

答案 2 :(得分:0)

fseek允许将文本追加到当前文件。因此,将文件指针设置在文件中的最后一个字符(!)之后,因为这是要附加新字符的地方。

从一开始:

01234         <---position
ABCDEFGHIJK   <---file content

从最后开始:

       43210  <---position
ABCDEFGHIJK   <---file content

因此,当您从头开始获取时,第0个字符是A 第三位是D。

但是当您从末尾获取时,第0个字符是EndOfFile 而-3rd是我。