关于 fread 功能的说明

Explanation about fread functionality

在通过此板搜索有关使用 C 将完整文件读入内存的信息时,我遇到了 fread() 的用法,这是我以前从未见过的。我正在努力理解它。

我的问题是:

是否有name/term这里正在做的事情?

size_t used 添加到 char *data 时发生了什么,fread 如何将其视为有效的 void *ptr

我要把作者 post 的代码放在这里,我也会 link 到 post。不幸的是,post 是旧的,锁定的,我没有足够的积分在这里发表评论要求澄清。

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

/* Size of each input chunk to be
   read and allocate for. */
#ifndef  READALL_CHUNK
#define  READALL_CHUNK  262144
#endif

#define  READALL_OK          0  /* Success */
#define  READALL_INVALID    -1  /* Invalid parameters */
#define  READALL_ERROR      -2  /* Stream error */
#define  READALL_TOOMUCH    -3  /* Too much input */
#define  READALL_NOMEM      -4  /* Out of memory */

/* This function returns one of the READALL_ constants above.
   If the return value is zero == READALL_OK, then:
     (*dataptr) points to a dynamically allocated buffer, with
     (*sizeptr) chars read from the file.
     The buffer is allocated for one extra char, which is NUL,
     and automatically appended after the data.
   Initial values of (*dataptr) and (*sizeptr) are ignored.
*/
int readall(FILE *in, char **dataptr, size_t *sizeptr)
{
    char  *data = NULL, *temp;
    size_t size = 0;
    size_t used = 0;
    size_t n;

    /* None of the parameters can be NULL. */
    if (in == NULL || dataptr == NULL || sizeptr == NULL)
        return READALL_INVALID;

    /* A read error already occurred? */
    if (ferror(in))
        return READALL_ERROR;

    while (1) {

        if (used + READALL_CHUNK + 1 > size) {
            size = used + READALL_CHUNK + 1;

            /* Overflow check. Some ANSI C compilers
               may optimize this away, though. */
            if (size <= used) {
                free(data);
                return READALL_TOOMUCH;
            }

            temp = realloc(data, size);
            if (temp == NULL) {
                free(data);
                return READALL_NOMEM;
            }
            data = temp;
        }

        n = fread(data + used, 1, READALL_CHUNK, in);
        if (n == 0)
            break;

        used += n;
    }

    if (ferror(in)) {
        free(data);
        return READALL_ERROR;
    }

    temp = realloc(data, used + 1);
    if (temp == NULL) {
        free(data);
        return READALL_NOMEM;
    }
    data = temp;
    data[used] = '[=10=]';

    *dataptr = data;
    *sizeptr = used;

    return READALL_OK;
}

Link: C Programming: How to read the whole file contents into a buffer

What is happening when the size_t used is being added to the char *data and how is this considered a valid void *ptr by fread?

实际上(*),指针只是一个数字,它引用(虚拟)内存中的地址。这里所做的是简单的指针运算:您可以将一个整数添加到一个指针,这会增加它的值,因此如果您的指针指向地址 1000 并且您添加 20,它现在指向地址 1020。因为 used 是始终是到目前为止读取的字节数,您将这么多字节指向 data 缓冲区。

但是还有一件事:只有当指针的数据类型的大小为 1 个字节(如 char (*))时,这才像描述的那样工作。因为当你做指针运算时,你不会将指针增加那么多字节,而是增加数据类型大小的倍数,所以你最终总是指向数组中元素的开头,而不是数组中的某个地方中间如果你正在处理 int。 IE。如果 int *x 指向地址 1000,而你 x += 20,那么 x 现在将指向地址 1080,也就是 x[20] 所在的位置。

and how is this considered a valid void *ptr by fread?

考虑到“指针只是数字”,fread 并不关心您是如何得出该指针值的。只要有有效的内存可以写入,它就会很乐意接受你传递给它的任何东西。

(*) 假设一个凡人都能访问的现代建筑。