如何从当前位置偏移 fseek

How to offset in fseek from current position

我无法从 SEEK_CUR 偏移:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    FILE * fp = fopen("txt", "w+b");
    if(!fp)
        return 1;
    
    fprintf(fp, "20");
    fseek(fp, 1, SEEK_CUR);
    fprintf(fp, "19");

    long size = ftell(fp) + 1;
    rewind(fp);
    char * buf = malloc(size+1);
    buf = memset(buf, 0, size+1); //should I really do this? becuase, after the "20" there will be [=10=] so I won't see the rest (` 19`)
    fread(buf, sizeof(char), size, fp);
    printf("%s\n",buf);

}

输出:

20

但应该是 20 19,我不能从该文件 fread(),为什么?

问题是您的 buf 不是 null-terminated。该数组的大小正好可以容纳文本文件的内容,没有任何空终止符。

尝试

char buf[size+1] = "";   /* initialize buf to all zeros, with room for null terminator */

字符串文字对象已经是 null-terminated,所以对于大多数用途来说,这是多余的:

char *str = "abc[=11=]";

字符串现在由两个空值终止,这在某些特殊情况下可能很有用。 Microsoft 提出了一种数据格式,用于 Windows 注册表,用于存储字符串列表。列表中的每个字符串都是 null-terminated,然后又一个空字节明确地终止了整个列表。我们可以在 C 中声明这样的东西:

char *windows_reg_style_list = "how[=12=]now[=12=]brown\cow[=12=]";

对于C语言中的普通字符串处理,"abc[=15=]"看起来和"abc"一样:都是长度为3的字符串,同样上面的数据看起来像字符串"how"

我认为,只有一种情况 C 源代码中的 "..." 表示法不会产生空终止字符串。那就是当它用作数组的初始值设定项时,该数组的大小恰好适合该字符数:

char no_null_term[4] = "abcd";

如果我们使它成为 [5],它将以 null 终止,并且 [3] 将是错误的,因为数组太小无法容纳 abcd[4] 允许作为一种特殊情况用于初始化不像 null-terminated 字符串那样表现的数组。

另请注意,要使用 ftell,流必须是二进制的:fopen(..., "w+b")。所以也就是说,ftell不需要return一个对应于写入文本流的字符数的值。

因此,您将“20”写入文件,然后跳过文件中前面的一个 byte/character,然后将“19”写入文件。跳过的字符需要写成某个值...那个值是 [=12=].

因此,您从文件中将“209”读取到一个由 memset 调用初始化为七个 [=12=] 字节的 buf 中。 buf 现在包含 "209[=16=][=16=]".

printf("%s\n", buf)buf 打印为 NUL 终止字符串,即直到出现第一个 NUL 字节。 NUL 字节紧跟在“20”之后,因此它只打印“20”。

如果你要用hexdump函数对缓冲区进行hexdump(写成练习)

hexdump(buf, size);

它会打印类似

的内容
0000  32 30 00 31 39 00      -                     20.19.