C-如果达到EOF,为什么fread()有两种可能的行为?

C-如果达到EOF,为什么fread()有两种可能的行为?,c,C,我不明白为什么函数fread()在这两个示例中的行为不同: 1) 我有一个包含一个short和一个char(大小为4字节,包括填充)的结构和一个由三个这样的结构组成的数组。如果我用fwrite()分别写入每个结构的short和char,然后用fread()将该文件读取到该结构类型的变量,我将一次读取4个字节(文件中有9个字节)所以你们可以看到,在第三次迭代中只剩下一个字节(每次迭代中都会丢失一个字节)。发生的情况是没有第三次读取,因为我只剩下一个字节,而fread必须读取4个字节 2) 一个

我不明白为什么函数fread()在这两个示例中的行为不同:

1)
我有一个包含一个short和一个char(大小为4字节,包括填充)的结构和一个由三个这样的结构组成的数组。如果我用fwrite()分别写入每个结构的short和char,然后用fread()将该文件读取到该结构类型的变量,我将一次读取4个字节(文件中有9个字节)所以你们可以看到,在第三次迭代中只剩下一个字节(每次迭代中都会丢失一个字节)。发生的情况是没有第三次读取,因为我只剩下一个字节,而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;
}  
。。。当达到
EOF

EOF
未“达到”。许多
函数返回
EOF
作为某个错误的信号,不给出该错误是什么。如果您想知道收到信号后出现了什么问题,请使用
feof()
和/或
ferror()
进行测试

如果达到EOF,为什么在一种情况下读取数据,而在另一种情况下不读取数据

“发生的事情是没有第三次读取,因为我只剩下一个字节,而fread必须读取4个字节。”这是一个可疑的前提

第一个代码读了3次。没有剩余的字节可读取

在这两个代码中,最后一次读取是部分读取,返回值为0。
fread()
(第一个代码没有打印第三次读取的结果。)

对于
fread()
,返回值为0并不意味着立即遇到“文件结束”-未读取任何内容。相反,0表示由于以下原因未发生完全读取:
*“文件结束”或部分读取。
*罕见的I/O错误


为什么会发生这种情况

在第二个代码中,结果可能因不确定行为而不同

fread()
。。。如果读取部分元素,其值为不确定C11dr§7.21.8.1 2

fread(&num,sizeof(num),1,fp)

一个信息量更大的例子

int main(void) {
  FILE *fp = fopen("FILE.DAT", "wb+");
  char c = 'a';
  printf("  %8X\n", c);
  fwrite(&c, sizeof(c), 1, fp);
  rewind(fp);

  unsigned num = rand();
  printf("  %8X\n", num);
  size_t len = fread(&num, sizeof(num), 1, fp);
  printf("%zu %8X\n", len, num);
  len = fread(&num, sizeof(num), 1, fp);
  printf("%zu\n", len);
  fclose(fp);

  return 0;
}
输出

        61  as expected
  5851F42D  as expected - some random value
0 5851F461  Indeterminate!  (in this case, looks like the LSByte was replaced.)
0           as expected
故事的寓意:在依赖读入缓冲区的内容之前,先评估
fread()
的返回值


1个不确定值

您是否可以编辑未指定的值或陷阱表示以提供一个?可运行代码比描述它的文本更具体。@Acorn没有文件,会编写一个新的文件(使用wb+,因为它既能写也能读)。您的两个示例中,哪一个是代码演示的示例?只是第一个,对吗?你对第一个例子有什么问题吗?或者问题是为什么第二个示例(我无法可视化,您没有显示代码)不同?您要求
fread
读取一个大小为4的项目。大小为4的单个项目不存在(而且显然
fread
不能返回0.5这样的值)。你希望发生什么
fread
允许读取较少数量的项(如第二个示例所示),但读取部分项是不合理的。第二个示例不检查
fread
的返回值,也不在调用int之前初始化int,然后检查int之后的值。您确定它读取的是一个整数的一部分吗?如果第一个程序中有第三次读取,那么为什么没有打印结果?@user3711671第三次读取返回0退出(int i=0;fread(&y,sizeof(y),1,fp);){}
循环-防止第三次调用
printf()
。需要说明的是,数据是在第三个
fread()
读取的,仅小于
sizeof(y)
字节。
        61  as expected
  5851F42D  as expected - some random value
0 5851F461  Indeterminate!  (in this case, looks like the LSByte was replaced.)
0           as expected