内存函数的使用让程序员拥有了更多的权限可以自由开辟和使用内存。
1:malloc函数的使用
void* malloc(size_t size);
这个函数向内存申请一块连续的空间,并返回这块空间的起始指针
注意点
1:如果开辟成功,则返回⼀个指向开辟好空间的指针。
2:如果开辟失败,则返回⼀个 NULL 指针,因此malloc的返回值⼀定要做检查
3:返回类型是void*,具体类型需要使用者自己来决定。
4:如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器
如图
在内存里面开辟了十个整型空间。
2:free函数
void free ( void * ptr);
free函数没有返回值,可以当成一个功能函数,主要是用于把我们自己开辟的函数给释放掉
注意
1:如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的
2:如果参数 ptr 是NULL指针,则函数什么事都不做
3:calloc
void * calloc ( size_t num, size_t size);
注意点
1:函数的功能是为 num 个大小为 size 的元素开辟⼀块空间,并且把空间的每个字节初始化为0。
2:与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。
如图
calloc全置为0;malloc置为cd。
4:recallo
void * realloc ( void * ptr, size_t size);
此函数的主要作用是将我们已经动态开辟的内存扩大或者缩小。
解释
ptr是起始地址size是需要改变的大小,也是新大小
返回值为调整之后的内存起始位置。
这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间;
realloc在调整内存空间的是存在两种情况:
情况1:原有空间之后有⾜够⼤的空间
情况2:原有空间之后没有⾜够⼤的空间
解析:
情况一在原来原地址的基础上追加新的空间;
情况二是开辟一块新的空间,并将原地址的数据拷贝到新空间里去。
5:对于动态内存开辟的成果与否的判断
我们有时候使用内存开辟函数可能会开辟失败,这时候就需要判断是否开辟成果
#include<stdio.h>
#include<stdlib.h>
int main()
{
int* p = (int*)malloc(sizeof(int) * 10);
//开始判断
if (p == NULL)
{
//如果判断失败,打印错误信息,退出函数
perror("malloc");
return 1;
}
//判断完毕
for (int i = 0; i < 10; i++)
{
*(p + i) = i + 1;
}
for (int i = 0; i < 10; i++)
{
printf("%d ", *(p + i));
}
free(p);
p = NULL;
return 0;
}
如图显示无法开辟
6:内存开辟的几个常见错误
1:对NULL指针的解引用操作
void test()
{
int *p = (int *)malloc(INT_MAX/4);
*p = 20;//如果p的值是NULL,就会有问题
free(p);
}
2:对动态开辟空间的越界访问
void test()
{
int i = 0;
int *p = (int *)malloc(10*sizeof(int));
if(NULL == p)
{
exit(EXIT_FAILURE);
}
for(i=0; i<=10; i++)
{
*(p+i) = i;//当i是10的时候越界访问
}
free(p);
}
3:对非动态开辟内存使用free释放
void test()
{
int a = 10;
int *p = &a;
free(p);//ok?
}
4:使用free释放⼀块动态开辟内存的⼀部分
void test()
{
int *p = (int *)malloc(100);
p++;
free(p);//p不再指向动态内存的起始位置
}
5:对同⼀块动态内存多次释放
void test()
{
int *p = (int *)malloc(100);
free(p);
free(p);//重复释放
}
6:动态开辟内存忘记释放(内存泄漏)
void test()
{
int *p = (int *)malloc(100);
if(NULL != p)
{
*p = 20;
}
}
int main()
{
test();
while(1);
}
本文的代码