我不明白为什么函数 fread() 在这两个示例中表现不同:
1)
我有一个带有short和char的结构(大小为4个字节,包括填充)和一个由三个这样的结构组成的数组。如果我用fwrite()分别写入每个结构的每个short和char,然后用fread读取该文件() 对于一个类型为该结构的变量,我将一次读取 4 个字节(文件中将有 9 个字节),因此您可以看到在第 3 次迭代中将留下一个字节(并且在第 3 次迭代中将丢失一个字节)每次迭代)。发生的情况是没有第三次读取,因为我只剩下一个字节,而 fread 必须读取 4 个字节。
2)
一个更简单的例子,如果我使用 fwrite() 将 1 字节字符写入文件,然后使用 fread() 将该文件的内容放入 4 字节 int 中,则整数将获取该数据。
为什么会发生这种情况?如果达到 EOF,为什么在一种情况下会读取数据,而在另一种情况下却不会读取数据?
这是第一个例子:
int main()
{
struct X { short int s; char c; } y, x[]=
{{0x3132,'3'},{0x3435,'6'},{0x3738,'9'}};
FILE *fp=fopen("FILE.DAT","wb+");
if (fp)
{
for(int i=0;i<sizeof(x)/sizeof(x[i]);)
{
fwrite(&x[i].s,sizeof(x[i].s),1,fp);
fwrite(&x[i].c,sizeof(x[i].c),1,fp);
i++;
}
rewind(fp);
for(int i=0;fread(&y,sizeof(y),1,fp);)
printf("%d:%x %c\n",++i, y.s, y.c);
fclose(fp);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
第二个例子:
int main()
{
FILE *fp=fopen("FILE.DAT","wb+");
char c = 'a';
fwrite(&c, sizeof(c), 1, fp);
rewind(fp);
int num;
fread(&num, sizeof(num), 1, fp);
fclose(fp);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
\n\n\n如果达到 EOF,为什么在一种情况下可以读取数据,而在另一种情况下却不能读取数据?
\n
“发生的情况是没有第三次读取,因为我只剩下一个字节,而 fread 必须读取 4 个字节。” 是一个值得怀疑的前提。
\n\n第一个代码确实读了 3 次。没有剩余字节可供读取。
\n\n在这两个代码中,最后一次读取都是部分读取,fread()
返回值为 0。@Useless
\n(第一个代码没有打印第三次读取的结果。)
对于fread()
,返回值 0 并不意味着立即遇到“文件结束” - 没有读取任何内容。相反,0 表示由于以下原因未发生完整读取:
\n * “文件结束”或部分读取。
\n * 罕见的 I/O 错误。
\n\n\n为什么会出现这种情况?
\n
在第二个代码中,由于不确定行为,结果可能会有所不同
\n\n\n\n\n\n
fread()
...如果读取部分元素,则其值不确定1 C11dr \xc2\xa77.21.8.1 2
fread(&num, sizeof(num), 1, fp)
结果可能会或可能不会达到预期。
一个信息更丰富的例子
\n\nint main(void) {\n FILE *fp = fopen("FILE.DAT", "wb+");\n char c = \'a\';\n printf(" %8X\\n", c);\n fwrite(&c, sizeof(c), 1, fp);\n rewind(fp);\n\n unsigned num = rand();\n printf(" %8X\\n", num);\n size_t len = fread(&num, sizeof(num), 1, fp);\n printf("%zu %8X\\n", len, num);\n len = fread(&num, sizeof(num), 1, fp);\n printf("%zu\\n", len);\n fclose(fp);\n\n return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n输出
\n\n 61 as expected\n 5851F42D as expected - some random value\n0 5851F461 Indeterminate! (in this case, looks like the LSByte was replaced.)\n0 as expected\n
Run Code Online (Sandbox Code Playgroud)\n\nfread()
这个故事的寓意是:根据读入缓冲区的内容来评估 before 的返回值。
1 个 不确定值
\既不是未指定的值也不是陷阱表示