读取N个字节时发生意外行为

时间:2015-09-23 17:31:36

标签: c binaryfiles fread

我试图一次读取四个字节的二进制文件。我想出了这个产生预期输出的代码:

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

int main() {
    char instr[4];
    FILE *fp;

    fp = fopen("tests", "rb");

    while( fread(instr, 1, 4, fp) != 0 ) {
        printf("%td", strlen(instr));
    }

    printf("\n");
}

输出

$ ./bin_files
44444

另一方面,这个修改版本产生了一个我无法解释的输出:

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

int main() {
    int i = 10;
    char instr[4];
    FILE *fp;

    fp = fopen("tests", "rb");

    printf("%d\n", i);

    while( fread(instr, 1, 4, fp) != 0 ) {
        printf("%td", strlen(instr));
    }

    printf("\n");
}

输出

$ ./bin_files
10
55555

为什么现在一次读取5个字节?

注意:我使用的是Macbook,这就是我使用%td代替%d的原因,就像打印字符串长度的教程一样。

2 个答案:

答案 0 :(得分:4)

strlen需要指向字符串的指针作为参数,但fread不会使其终止其缓冲区。使用累积的fread返回值来获取读取的大小。

此外,使用%zu转换规范来打印size_t值(strlen返回的值的类型)。 %tu用于ptrdiff_t类型。

答案 1 :(得分:1)

fread未在数组末尾添加NUL字符('\0')。你拥有的不是一个字符串。

并且strlen需要一个参数作为字符串,字符串的长度由终止NUL字符决定。因此这种行为。

您可以在数组中手动​​添加NUL字符,使其成为字符串。

同样strlen返回size_t类型的长度,因此请使用%zu说明符进行打印。