calloc()、fread 和 fwrite() 都将在交换计数和大小参数的情况下尝试相同的工作。顺便说一下,fread/fwrite 和 calloc 以不同的顺序指定这些参数:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
void *calloc(size_t nmemb, size_t size);
虽然calloc() 没有区别,但转置fread() 和fwrite() 中的参数会影响返回值,即成功读取或写入的元素数。确保使用正确的值并将返回值与nmemb 参数(第三个参数)进行比较:
#include <stdio.h>
struct chunk {
int a, b, c;
};
size_t copy_chunks(FILE *from, FILE *to) {
struct chunk array[64];
size_t total = 0, nread, nwritten;
while ((nread = fread(array, sizeof(*array), 64)) != 0) {
nwritten = fread(array, sizeof(*array), nread);
total += nwritten;
if (nwritten != nread) {
fprintf(stderr, "write error: wrote %zu of %zu elements\n", nwritten, nread);
break;
}
return total;
}
请注意,在上述写入错误的情况下,实际写入了多少字节是不确定的。
这是来自 C 标准的文本:
7.21.8.2 fwrite 函数
概要
size_t fwrite(const void * restrict ptr,
size_t size, size_t nmemb,
FILE * restrict stream);
fwrite 函数从ptr 指向的数组中,将大小由size 指定的nmemb 元素写入stream 指向的流。对于每个对象,对fputc 函数进行size 调用,从恰好覆盖对象的unsigned char 数组中获取值(按顺序)。流的文件位置指示器(如果已定义)按成功写入的字符数提前。如果发生错误,则流的文件位置指示符的结果值是不确定的。
退货
fwrite函数返回成功写入的元素个数,只有遇到写入错误才会小于nmemb。如果size 或nmemb 为零,则fwrite 返回零并且流的状态保持不变。
如果您不关心返回值,那确实没有什么区别……但是忽略错误可能会有所不同,具体取决于意外情况的后果。还要考虑您的代码的后续读者,并通过使用正确的参数使他们更容易理解它的作用。
其他库函数采用void * 指针、大小和计数参数,如果您以错误的顺序传递它们,如果不是未定义,则行为会受到严重影响:
void *bsearch(const void *key, const void *base,
size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
void *bsearch_s(const void *key, const void *base,
rsize_t nmemb, rsize_t size,
int (*compar)(const void *k, const void *y, void *context),
void *context);
errno_t qsort_s(void *base, rsize_t nmemb, rsize_t size,
int (*compar)(const void *x, const void *y, void *context),
void *context);