关于摩擦功能的说明

发布于 2025-01-23 08:31:18 字数 2766 浏览 2 评论 0原文

在浏览该板上以获取有关使用C中的完整文件读取完整文件的信息时,我遇到了以前从未见过的fread()的使用。我试图理解它。

我的问题是:

这里有什么名字/术语吗?

size_t使用正在添加到char *data时发生了什么,如何将其视为有效void *ptr *ptr by fread

我将从作者的帖子中放入此处的代码,我也将链接到帖子。不幸的是,该帖子是旧的,被锁定的,我在这里没有足够的积分来发表评论,要求澄清一下。

#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] = '\0';

    *dataptr = data;
    *sizeptr = used;

    return READALL_OK;
}

链接: c编程:如何阅读整个文件内容到缓冲区

While searching through this board for information about reading a full file into memory using C, I came across a use of fread() that I haven't seen before. I'm trying to understand it.

My questions are:

Is there a name/term for what is being done here?

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?

I'm going to put the code from the author's post in here and I'll link to the post as well. Unfortunately, the post is old, locked, and I don't have enough points here to leave a comment asking for clarification on it.

#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] = '\0';

    *dataptr = data;
    *sizeptr = used;

    return READALL_OK;
}

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

陌若浮生 2025-01-30 08:31:18

当使用的size_t被添加到char *数据中时发生了什么事,如何将其视为有效的void *ptr?

在实践(*)实践中,指针只是一个数字,它引用了(虚拟)内存中的地址。在这里完成的是简单的指针算术:您可以在指针中添加整数,从而增加其值,因此,如果您的指针指向地址1000并添加20个,现在指向地址1020。由于使用了始终是到目前为止读取的字节数,您可以将许多字节指向data缓冲区。

但是还有一件事:如果指针的数据类型的大小为1个字节,则仅如描述的那样起作用(如char所示(*))。因为当您执行指针算术时,您不会通过许多字节来增加指针,而是通过数据类型的大小的倍数来增加指针如果您要处理int,则中间。即,如果您有int *x要点地址为1000,然后进行x += 20,则x将指向地址1080现在,这是x [20]的位置。

,如何将其视为弗雷德的有效void *ptr?

考虑“指针只是数字”,fread不在乎您如何达到指针值。只要有有效的内存要写入,它就会高兴地接受您通过的任何内容。

(*)假设单纯的凡人可以访问现代建筑。

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?

In practice(*), a pointer is just a number, which references an address in (virtual) memory. What's being done here is simple pointer arithmetic: You can add an integer to a pointer, which increases its value, so if your pointer pointed to address 1000 and you add 20, it now points to address 1020. Since used is always the number of bytes read so far, you point this many bytes into the data buffer.

But there's one more thing: This only works as described if the data type of the pointer has a size of 1 byte (as char does(*)). Because when you do pointer arithmetic, you don't increase the pointer by that many bytes, but really by multiples of the data type's size, so you always end up pointing to the start of an element in your array, and not somewhere in the middle if you're dealing with int. I.e. if you have int *x which points to address 1000, and you do x += 20, then x will point to address 1080 now, which is where x[20] would be located.

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

Considering "pointers are just numbers", fread doesn't care how you arrived at that pointer value. As long as there is valid memory to write to, it will happily accept whatever you pass it.

(*) Assuming a modern architecture accessible by mere mortals.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文