目录
(三)void *calloc(size_t num,size_t size )
(四)void*realloc(void *memblock ,size_t size)
1.变量名称是一种外在体现,是给程序员看的,程序内部指令都是通过地址进行操作的
2.每个函数在调用的时候都会分配一块栈空间,作为函数的局部存储,函数内定义的局部变量,使用空间都是在函数栈空间中分配的。
!一个 函数内其实如果定义局部变量并不是无限制定义的,如果定义一个超大变量,超过了函数空间大小就会报错。
在一个函数中定义一个变量的注意事项:
局部变量:栈空间上内存分
1.不能过大,会超出函数栈空间
2.变量出了作用域空间就会被释放
3.当我们有一些需求:保存一组数据,但是也不知道数据有多少个,因此只能按照上限个数提前定义好数组,但是会造成空间浪费,很多实际情况用不了。基于以上的局部变量的一些限制,提出堆上内存分配。
0xFFFFFFFF |
栈 分配地址从高往低,先定义的变量地址高。空间大小不固定,程序编译阶 段无法确定。如函数递归,栈空间不断分配。
|
堆 分配地址从低往高,先定义的变量地址低。空间大小不固定,程序编译 阶段无法确定。如动态空间申请。 |
数据段 所占用空间大小在编译完毕后是固定的 |
代码段 所占用空间大小在编译完毕后是固定的 |
0x00000000 |
在堆区分配内存——动态内存分配——分内存有个特点:
1.手动申请,手动释放(出了申请位置的作用域也不会释放)
2.需要多少申请多少(按需分配)
3.空间在堆上分配,不占用栈空间(因此不怕栈溢出)
功能:申请size字节大小的空间
返回值:成功则返回申请到的空间的首地址;失败则返回NULL
注意:在动态空间申请的时候一定要进行返回值的判断,因为空间申请有可能失败
功能:释放动态申请的空间参数,参数start是动态申请空间时返回的首地址
注意:1.不要对局部变量进行free;2.空间释放只能从动态申请的首地址释放,不能是从中途释
动态地址分配,申请空间是一整块连续空间,因此可以当做数组来用
功能:为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0
返回值:成功则返回申请到的空间的首地址;失败则返回NULL
功能:重新为原来的空间扩容。原先使用的空间必须有足够的空闲空间,否则就申请新的空间,将数据拷贝过去,返回新地址。
memblock:原先老的空间首地址; size:要扩容到的大小;
注意:成功则会释放原先的空间,返回新的空间首地址(在原地址扩容成功则不会释放),失败返回NULL。realloc如果传入的源空间地址为空则相当于malloc。
扩容的两种情况:
情况1:原有空间之后有足够大的空间
要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。
情况2:原有空间之后没有足够大的空间
原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来
使用。这样函数返回的是一个新的内存地址。
1.对NULL指针的解引用操作
2.对动态开辟空间的越界访问
3.对非动态开辟内存使用free释放
4.使用free释放一块动态开辟内存的一部分
5.对同一块动态内存多次释放
6.动态开辟内存忘记释放(内存泄漏)
ps:
野指针:指向了一块不能正常访问的空间
如果申请了一块内存,将地址赋值给了指针变量p,然后对p进行free,这时候只是把指针p指向的空间释放了并没有修改p变量的指向。意味着这首p指针就是一个野指针。
malloc和free一定成对出现。
1.不要对局部变量的地址进行释放
2.动态申请的空间不要从中释放
3.释放了指针变量指向的空间后,指针变量会变为野指针,要注意指向,不要继续访问原员空间,
4.动态申请的空间不要重复释放
5.扩容成功后,有可能原空间会被释放掉,因此一定要保存新的地址
6.申请与释放一定要成对出现
简单理解不是一个数组,是和结构体搭配使用的一种数据结构。
定义:在一个结构体中。定义一个没有大小的数组,数组的空间通过动态内存申请。
例:
- typedef struct st_type
- {
- int i;
- int a[0];//柔性数组成员
- }type_a;
- typedef struct st_type
- {
- int i;
- int a[];//柔性数组成员
- }type_a;
1.结构中的柔性数组成员前面必须至少一个其他成员,柔性数组要放在结构体的最后边。
2.sizeof 返回的这种结构大小不包括柔性数组的内存。
3.包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
- typedef struct st_type
- {
- int i;
- int a[0];//柔性数组成员
- }type_a;
- printf("%d\n", sizeof(type_a));//输出的是4
- int i = 0;
- type_a *p = (type_a*)malloc(sizeof(type_a)+100*sizeof(int));
- //业务处理
- p->i = 100;
- for(i=0; i<100; i++)
- {
- p->a[i] = i;
- }
- free(p);
1.方便内存释放。
2.这样有利于访问速度。