11.C语言 malloc() calloc() realloc()分配内存
目录
malloc
好处
坏处
总结
calloc
参数说明
作用
与 malloc 的区别
示例
优点
缺点
总结
realloc
参数说明
作用
示例
优点
缺点
注意事项
总结
总结区别
对比表格
malloc
函数功能:分配内存给
void* malloc(size_t size);
来看一下deepseek的解释,其实deepseek的解释好,涵盖了很多方面
malloc
是 C 语言中用于动态分配内存的函数,其原型为:
size:需要分配的内存大小(以字节为单位)。
返回值:成功时返回指向分配内存的指针,失败时返回
NULL
。好处
动态内存分配:程序运行时根据需要分配内存,避免静态分配的局限性。
灵活管理内存:适用于不确定内存需求的情况,如动态数组、链表等数据结构。
提高资源利用率:按需分配,减少内存浪费。
坏处
内存泄漏:未使用
free
释放内存会导致内存泄漏,长期运行可能耗尽系统资源。碎片化:频繁分配和释放可能导致内存碎片,降低内存使用效率。
性能开销:动态分配比静态分配慢,频繁操作可能影响性能。
未初始化内存:
malloc
分配的内存未初始化,直接使用可能导致未定义行为。总结
malloc
提供了动态内存分配的灵活性,但需谨慎管理以避免内存泄漏和碎片化问题。
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
//malloc 分配内存
void test01() {
int *p = malloc(sizeof(int)*10);
for (int i = 0; i< 10; i++)
{
printf("p[%d] = %d\n",i,p[i]);
}
}
int main() {
printf("mamory info\n");
test01();
return EXIT_SUCCESS;
}
运行结果:
赋值
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
//malloc 分配内存
void test01() {
int *p = malloc(sizeof(int)*10);
for (int i = 0; i< 10; i++)
{
p[i] = i + 100;
}
for (int i = 0; i < 10; i++)
{
printf("p[%d] = %d\n", i, p[i]);
}
}
int main() {
printf("mamory info\n");
test01();
return EXIT_SUCCESS;
}
calloc
#include <stdlib.h>
void *calloc(size_t nmemb, size_t size);
功能
calloc
是 C 语言中用于动态分配内存的函数,与malloc
类似,但它在分配内存的同时会将内存初始化为零。其原型为参数说明
num:需要分配的元素个数。
size:每个元素的大小(以字节为单位)。
返回值:成功时返回指向分配内存的指针,失败时返回
NULL
。作用
分配内存:分配
num * size
字节的内存空间。初始化内存:将分配的内存块中的所有位初始化为零。
与
malloc
的区别
特性 malloc
calloc
初始化 不初始化内存,内容为随机值 初始化内存为 0 参数 接受总字节数 接受元素个数和每个元素的大小 适用场景 不需要初始化时使用 需要初始化内存为零时使用 示例
#include <stdio.h> #include <stdlib.h> int main() { int *arr; int n = 5; // 使用 calloc 分配并初始化内存 arr = (int*)calloc(n, sizeof(int)); if (arr == NULL) { printf("Memory allocation failed\n"); return 1; } // 打印初始化的值(应为 0) for (int i = 0; i < n; i++) { printf("%d ", arr[i]); // 输出: 0 0 0 0 0 } // 释放内存 free(arr); return 0; }
优点
自动初始化:省去手动初始化的步骤,避免使用未初始化的内存。
适合数组和结构体:特别适合需要初始化为零的场景,如数组、结构体等。
缺点
性能开销:由于需要初始化内存,
calloc
的性能略低于malloc
。不适用于非零初始化:如果不需要初始化为零,使用
malloc
更高效。总结
calloc
:适合需要分配并初始化内存为零的场景。
malloc
:适合不需要初始化或需要手动初始化的场景。根据具体需求选择合适的函数!
//calloc 分配内存
void test02() {
//参数1长度,参数2类型的大小
int* p = calloc(10,sizeof(int)); //与malloc的不同是在于堆区的内容初始化成0,相同的地方都是在堆区分配内存
for (int i = 0; i < 10; i++)
{
printf("p[%d] = %d\n", i, p[i]);
}
if (p!= NULL) {
free(p);
p = NULL;//防止野指针
}
}
int main() {
printf("mamory info\n");
test02();
return EXIT_SUCCESS;
}
realloc
realloc重新分配内存,在原有的内存上加更多内存
realloc
是 C 语言中用于调整已分配内存块大小的函数。它可以在不丢失原有数据的情况下,扩大或缩小内存块的大小。其原型为:
void* realloc(void* ptr, size_t size);
参数说明
ptr:指向之前分配的内存块的指针(由
malloc
、calloc
或realloc
返回)。如果ptr
为NULL
,则realloc
的行为等同于malloc
。size:新的内存块大小(以字节为单位)。如果
size
为 0 且ptr
不为NULL
,则realloc
的行为等同于free
。返回值:成功时返回指向新内存块的指针,失败时返回
NULL
,且原内存块保持不变。
作用
调整内存大小:
扩大内存块:如果新的大小大于原大小,
realloc
会尝试扩展内存块,保留原有数据。缩小内存块:如果新的大小小于原大小,
realloc
会截断内存块,保留新大小范围内的数据。重新分配内存:
如果原内存块无法扩展,
realloc
会分配一个新的内存块,将原数据复制到新内存块中,并释放原内存块。释放内存:
如果
size
为 0 且ptr
不为NULL
,realloc
会释放原内存块,并返回NULL
。示例
#include <stdio.h> #include <stdlib.h> int main() { int *arr; int n = 5; // 初始分配内存 arr = (int*)malloc(n * sizeof(int)); if (arr == NULL) { printf("Memory allocation failed\n"); return 1; } // 初始化数据 for (int i = 0; i < n; i++) { arr[i] = i + 1; } // 调整内存大小 int new_n = 10; arr = (int*)realloc(arr, new_n * sizeof(int)); if (arr == NULL) { printf("Memory reallocation failed\n"); return 1; } // 初始化新增部分 for (int i = n; i < new_n; i++) { arr[i] = i + 1; } // 打印结果 for (int i = 0; i < new_n; i++) { printf("%d ", arr[i]); // 输出: 1 2 3 4 5 6 7 8 9 10 } // 释放内存 free(arr); return 0; }
优点
动态调整内存:可以根据需要动态调整内存大小,避免内存浪费。
保留数据:在扩展内存时,原有数据会被保留。
灵活性:适合处理动态变化的数据结构,如动态数组、链表等。
缺点
性能开销:如果无法在原内存块上扩展,
realloc
需要分配新内存并复制数据,这会带来额外的性能开销。内存碎片:频繁调整内存大小可能导致内存碎片。
潜在的内存泄漏:如果
realloc
失败并返回NULL
,原内存块不会被释放,可能导致内存泄漏。
注意事项
检查返回值:
realloc
可能失败,返回NULL
,因此需要检查返回值。避免直接覆盖指针:
ptr = realloc(ptr, new_size); // 错误:如果 realloc 失败,ptr 会丢失
正确做法:
void *new_ptr = realloc(ptr, new_size); if (new_ptr == NULL) { // 处理错误 } else { ptr = new_ptr; }
释放内存:使用
realloc
后,仍需使用free
释放内存。总结
realloc
是动态内存管理的重要工具,适合需要动态调整内存大小的场景。使用时需注意检查返回值,避免内存泄漏和性能问题。
结合
malloc
、calloc
和free
,可以实现灵活的内存管理。
情况1:分配的大小足够,不会继续增加。可以看运行结果,地址内存不会变
//realloc重新分配内存
void test03() {
int* p = malloc(sizeof(int)*10);
printf("p: %d\n", &p);
for (int i = 0; i < 10; i++) {
p[i] = i;
}
p = realloc(p,sizeof(int)*11); //在原有的基础上加11,如果原有的内存不够,才会增加
for (int i = 0; i < 10; i++) {
printf("p[%d] = %d\n",i,p[i]);
}
printf("p: %d\n", &p);
}
int main() {
printf("mamory info\n");
//test01();
//test02();
test03();
return EXIT_SUCCESS;
}
运行结果:
总结区别
对比表格
特性 | malloc | calloc | realloc |
---|---|---|---|
功能 | 分配内存 | 分配并初始化内存 | 调整已分配内存的大小 |
初始化 | 不初始化 | 初始化为零 | 保留原有数据(如果可能) |
参数 | 总字节数 (size ) | 元素个数 (num ) 和元素大小 (size ) | 原指针 (ptr ) 和新大小 (size ) |
返回值 | 指向分配内存的指针 | 指向分配内存的指针 | 指向新内存块的指针 |
适用场景 | 不需要初始化时使用 | 需要初始化内存为零时使用 | 需要调整内存大小时使用 |
malloc
:适合不需要初始化内存的场景。
calloc
:适合需要初始化内存为零的场景。
realloc
:适合需要动态调整内存大小的场景。
查看接口
cplusplus.com - The C++ Resources Networkhttps://legacy.cplusplus.com/