1、引入:
一般开辟内存空间的方法:
int g_val = 0; //在栈空间上开辟4个byte。
int array [10] = {0}; //在栈空间上开辟40个byte的连续空间。
或者int array [] = {0,1};//在栈空间上开辟8个字节的连续空间。
但是上述开辟空间的方式有两个特点:
1、空间开辟大小是固定的。
2、数组在申明的时候,必须指定数组的长度,或是初始化所需要的元素,它所需要的内存在编译期间分配。
这就意味着我们需要在创建的时候就知道我们需要多少的空间,但是有时候我们所需的空间大小往往是在编写的过程中才知道,或者说需要调整,但是上述的方法显然是不能满足我们的需求的,此时就需要动态内存分配:
首先要了解内存的布局:
内存大致被分为这么几个区域,其中内核空间是用来留给操作系统以及关键组件的,是用户代码不能读写的,栈区主要用来存放局部变量以及函数形参,堆区主要用来动态内存分配,所谓的数据段也就是静态区,主要用来存放static修饰的静态变量和创建的全局变量。
所以,动态内存是在堆区开辟的。
2、动态内存开辟函数介绍:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main()
{
int i = 0;
int* p = (int*)calloc(5, sizeof(int));//开辟动态内存空间
if (p != NULL)
{
//使用
for (i = 0; i < 5; i++)
{
*(p + i) = i;
}
for (i = 0; i < 5; i++)
{
printf("%d ", *(p + i));
}
}
else
{
printf("%s\n", strerror(errno));
}
//释放
free(p);
p = NULL;
return 0;
}
malloc 和 calloc 的区别:
malloc函数在开辟空间时,只是给了一块空间的访问权限,但并未对所申请区域的数据进行初始化,而calloc函数在开辟时,会将所申请区域的数据全部初始化为0。(未初始化时内存空间内存储的是随机值)
如果我们在申请动态内存空间时,需要对所申请的空间初始化,那么可以使用calloc函数。
<3> realloc
realloc函数的出现让动态内存管理更加灵活。
realloc函数可以对动态开辟的内存大小进行调整。
memblock参数是需要调整的动态内存空间的指针,size参数是所需调整到的字节数。
返回值是调整之后的空间的首地址。
注:realloc函数在调整空间时,会有两种情况:
1、原有空间之后有足够大的空间
那么就会在原有空间后面直接追加空间,原来空间的数据不发生改变。返回的指针指向的空间仍然是realloc之前的空间,不过是扩容了。
2、原有空间之后没有足够大的空间
扩展的方法是:在堆空间上另外找一块合适大小的连续空间来使用,原有的数据会被挪到新开辟的空间中,返回的指针指向的空间也是新的。原来的那块空间就会被回收。
如果扩容失败,会返回NULL 。
所以在接收realloc返回的指针时,要创建一个中间变量,用来判断是否开辟成功,再决定是否将新开辟的空间交给原来的指针保管。若是直接将返回值交给缘来的指针,若开辟失败,原指针就被置为NULL,原数据也就不能访问了
使用例子:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main()
{
int i = 0;
int* p = (int*)calloc(5, sizeof(int));//开辟动态内存空间
if (p != NULL)
{
//使用
for (i = 0; i < 5; i++)
{
*(p + i) = i;
}
for (i = 0; i < 5; i++)
{
printf("%d ", *(p + i));
}
}
else
{
printf("%s\n", strerror(errno));
}
printf("\n");
//调整
int* ptr = (int*)realloc(p, sizeof(int) * 10);
if (ptr != NULL)
{
//使用
p = ptr;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
for (i = 0; i < 10; i++)
{
printf("%d ", *(p + i));
}
}
else
{
printf("扩容失败\n");
}
//释放
free(p);
p = NULL;
return 0;
}
其中ptr就是一个中间变量。
特殊情况:
若给relloc传入空指针,即realloc(NULL, size);此时功能类似malloc 。
水平有限,欢迎指正。(下一篇就写写使用这些函数容易出错的点吧)