关于 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
并不关心您是如何得出该指针值的。只要有有效的内存可以写入,它就会很乐意接受你传递给它的任何东西。
(*) 假设一个凡人都能访问的现代建筑。
在通过此板搜索有关使用 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
并不关心您是如何得出该指针值的。只要有有效的内存可以写入,它就会很乐意接受你传递给它的任何东西。
(*) 假设一个凡人都能访问的现代建筑。