试图了解 realloc 和 malloc 函数是如何工作的
Trying to understand how does realloc and malloc function works
抱歉,如果问题很基础,但我真的不明白为什么如果我不添加“+ 1”,程序就不会打印所有字母
a = realloc(a, sizeof(char)*(i + 1));
也在这里
*(a + i) = letra;
"a"的位置是不是每过一次就变大?
我想情况并非如此,但我不太确定。
#include <stdio.h>
#include <stdlib.h>
char *copiarFrase();
int main()
{
char *frase;
frase = copiarFrase();
printf("Frase: %s", frase);
free(frase);
return 0;
}
char *copiarFrase()
{
FILE *archivo;
char letra;
char *a;
int i = 0;
archivo = fopen("frases.txt", "r");
a = malloc(sizeof(char));
letra = fgetc(archivo);
while(letra != EOF)
{
*(a + i) = letra;
i++;
a = realloc(a, sizeof(char)*(i + 1));
letra = fgetc(archivo);
}
return a;
}
简而言之,您的代码所做的是一次从文件中读取 1 个字节,然后不断地将读取的内容写入内存中的新位置。
步骤如下:
为一个char分配1个字节(8位)的内存来存储文件的内容:
a = malloc(sizeof(char));
注意:由于这对于整个文件来说内存不足,您的程序不断地重新分配,在循环中一次分配 1 个字节(下面对此有更多评论)。
打开文件流:
archivo = fopen("frases.txt", "r");
从流存档中读取第一个字母 (frases.txt):
letra = fgetc(archivo);
开始循环读取直到文件结尾 (EOF):
while(letra != EOF)
{
*(a + i) = letra;
这将从 fgetc()
读取的字母复制到您的指针 a
-- 这 -> *(a + i)
是指针算术。它本质上意味着从内存地址 a
引用内存中的位置 i
字节。只有 *a
没有 ( + i)
会将字母写入内存的开头(字符指针)。
您的主要问题:
为什么 (i + 1)
在 a = realloc(a, sizeof(char)*(i + 1));
中?
realloc()
创建请求大小的新内存并将输入缓冲区复制到新的 space,这可能是 @hans 批评代码的原因(以及你一次读取整个文件一个字符)。一个轻微的改进是一次读取 1024 个字符,然后重新分配。要了解有关如何从文件中读取字符的更多信息,请研究堆栈溢出或 google.
别忘了,i
在这段代码中一直递增1:i++
.
例如, 如果您已经将 "hola mundo"
从文件读取到缓冲区 a
,则 i
的值为10
。 realloc()
在内存中创建一个全新的位置。因此,如果您分配了 10 个字节,那么对于 "hola mundo"
和终止的 NULL
字节来说就足够了:'[=33=]'
,但对于下一个字符 '!'
和 '[ =33=]'
字节。因此,您需要为 i
分配内存(对于 NULL 字节,当前长度 + 1) + 1
更多用于下一个字符。
抱歉,如果问题很基础,但我真的不明白为什么如果我不添加“+ 1”,程序就不会打印所有字母
a = realloc(a, sizeof(char)*(i + 1));
也在这里
*(a + i) = letra;
"a"的位置是不是每过一次就变大? 我想情况并非如此,但我不太确定。
#include <stdio.h>
#include <stdlib.h>
char *copiarFrase();
int main()
{
char *frase;
frase = copiarFrase();
printf("Frase: %s", frase);
free(frase);
return 0;
}
char *copiarFrase()
{
FILE *archivo;
char letra;
char *a;
int i = 0;
archivo = fopen("frases.txt", "r");
a = malloc(sizeof(char));
letra = fgetc(archivo);
while(letra != EOF)
{
*(a + i) = letra;
i++;
a = realloc(a, sizeof(char)*(i + 1));
letra = fgetc(archivo);
}
return a;
}
简而言之,您的代码所做的是一次从文件中读取 1 个字节,然后不断地将读取的内容写入内存中的新位置。
步骤如下:
为一个char分配1个字节(8位)的内存来存储文件的内容:
a = malloc(sizeof(char));
注意:由于这对于整个文件来说内存不足,您的程序不断地重新分配,在循环中一次分配 1 个字节(下面对此有更多评论)。
打开文件流:
archivo = fopen("frases.txt", "r");
从流存档中读取第一个字母 (frases.txt):
letra = fgetc(archivo);
开始循环读取直到文件结尾 (EOF):
while(letra != EOF)
{
*(a + i) = letra;
这将从 fgetc()
读取的字母复制到您的指针 a
-- 这 -> *(a + i)
是指针算术。它本质上意味着从内存地址 a
引用内存中的位置 i
字节。只有 *a
没有 ( + i)
会将字母写入内存的开头(字符指针)。
您的主要问题:
为什么 (i + 1)
在 a = realloc(a, sizeof(char)*(i + 1));
中?
realloc()
创建请求大小的新内存并将输入缓冲区复制到新的 space,这可能是 @hans 批评代码的原因(以及你一次读取整个文件一个字符)。一个轻微的改进是一次读取 1024 个字符,然后重新分配。要了解有关如何从文件中读取字符的更多信息,请研究堆栈溢出或 google.
别忘了,i
在这段代码中一直递增1:i++
.
例如, 如果您已经将 "hola mundo"
从文件读取到缓冲区 a
,则 i
的值为10
。 realloc()
在内存中创建一个全新的位置。因此,如果您分配了 10 个字节,那么对于 "hola mundo"
和终止的 NULL
字节来说就足够了:'[=33=]'
,但对于下一个字符 '!'
和 '[ =33=]'
字节。因此,您需要为 i
分配内存(对于 NULL 字节,当前长度 + 1) + 1
更多用于下一个字符。