我应该如何考虑 fread() 的参数?

How should I think about the parameters of fread()?

很容易找到 C 风格的流行约定 I/O。更困难的是找到关于为什么他们是这样的解释。常见的阅读语句如下:

fread(buffer, sizeof(buffer), 1, ptr);

首先,while (!feof(ptr)) 错误的 并且是一个非常糟糕的反模式。在某些情况下它可以工作,但它几乎总是比正确的惯用用法更复杂。 fread 或其他 stdio 读取函数的 return 值 已经告诉你它是否没有成功 ,你通常需要能够立即处理而不是而不是等待下一个循环迭代开始。如果您正在学习的任何资源正在教授这个 while (!feof(ptr)) 东西,您可能应该停止将其作为学习 C 的来源。

现在,关于您关于 sizen 参数的具体问题:将它们分开是完全没有必要的,也没有用。只需传递所需的长度以读取其中一个,并为另一个传递 1 。如果您希望能够确定在遇到文件末尾或错误时已经读取了多少字节,则需要将 1 传递给 size 并将请求的字节数传递为 n。否则,如果任何比预期短的读取都是错误的,有时切换它们是有意义的;那么唯一可能的 return 值是 1 和 0(分别为成功和错误)。

为了理解为什么,您如何使用这两个参数并不重要,指定了所有 stdio 读取函数,包括 fread就好像它们是通过重复调用 fgetc 发生的一样。您是否有 size*n 个这样的电话或 n*size 个这样的电话并不重要,因为数字的乘法通勤。

size_t fread(void * restrict ptr, size_t size, size_t n, FILE * restrict stream);

How should a programmer think about using the parameters size and n of fread()?

读入数组时:

size 是被调用指针的取消引用类型的大小。

n中的元素个数。

some_type destination[max_number_of_elements];
size_t num_read = fread(destination, sizeof *destination, max_number_of_elements, inf);
printf("Number of elements read %zu\n", num_read);

if (num_read == 0) {
  if (feof(inf)) puts("Nothing read as at end-of-file");
  else if (ferror(inf)) puts("Input error occurred");
  else {
    // since sizeof *destination and max_number_of_elements cannot be 0 here
    // something strange has occurred (UB somewhere prior?)
  }

For example, if my input file is 100 bytes, should I opt for a larger size with fewer n or read more objects of a smaller size?

案例中,数据大小为1,最大计数100。

#define MAX_FILE_SIZE 100
uint8_t destination[MAX_FILE_SIZE];
size_t num_read = fread(destination, sizeof *destination, MAX_FILE_SIZE, inf);

If the size-to-be-read and n exceed the byte-size of an input file, what happens?

目的地未填写。使用return值来判断。

Are the excess bytes that were read composed, colloquially speaking, of "junk values"?

没有。 fread() 之前的值保持不变(只要 return 不是 0 且 ferror() 未设置)。如果目的地不是 initialized/assigned,那么是的,它可能是垃圾。


单独的 size, n 允许 fread() 正常运行,即使 size * n 溢出 size_t 数学。对于当前的平面内存模型,很少需要这样做。