1.动态内存分配
向内存申请空间的方式有两种方式
1.单个值 2.一组值
int i=1; char arr[10]={0};
1)但开辟的空间大小是固定的,大小是不可变化的
2)数组在声明的时候,必须指定数组的长度,数组空间一旦确定了大小就不能调整
有时候我们需要的空间的大小在程序运行时才能知道,那数组开辟空间的方式就不能满足了,存在大(浪费),小(不够),刚刚好的情况
C语言引入了动态内存开辟,让程序员可以自己申请和释放空间,就可以比较灵活
2.malloc和free(maiioc和free都声明在stdlib.h头文件中)
2.1malloc
void * malloc ( size_t size);
参数的单位是字节
向内存申请一块连续可用的空间,并返回空间的起始地址
1)如果开辟成功就返回空间的起始地址
2)如果开辟失败就返回一个NULL指针,所以malloc的返回值一定要做检查
3)返回值的类型是void*,所以maloc不知道开辟空间的类型,具体在使用时再强制类型转换
4)如果参数size为0,malloc的行为是标准未定义的,取决于编译器
malloc申请的空间和数组的空间有什么区别
1.动态内存的大小是可以调整的
1.开辟空间的位置不一样
使用
2.2free函数
专门用来做动态内存的释放和回收的
void free ( void * ptr );
1)只用于动态申请的内存空间的释放和回收
2)如果ptr是空指针,则函数什么事都不做
err
3.calloc和realloc
3.1calloc
calloc函数也是用来动态内存分配的
void * calloc ( size_t num,size_t size);
1)为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0
2)与malloc函数的区别在于calloc会在返回地址之前把申请的空间的每个字节初始化为全0
如果我们对申请的内存空间的内容要求初始化,那么可以很方便地使用calloc函数来完成
3)申请的空间也是用free释放
使用
3.2realloc函数(调整内存空间)
realloc函数让动态内存管理更加灵活,可以做到对动态开辟的内存大小的调整
void * realloc (void * ptr ,size_t size);
1)ptr是要调整的内存地址
2)size是调整之后的新大小
3)返回值是调整之后的内存起始地址
4)这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间
5)有两种情况
1.原有空间之后有足够大的空间
2.原有空间之后没有足够大的空间
使用
realloc开辟失败时,则不能拿p直接接收
附:
4.常见的动态内存的错误
4.1对NULL指针的解引用操作
4.2对动态开辟的空间越界访问
4.3对非动态开辟内存使用free释放
4.4使用free释放一块动态开辟内存的一部分
这里的free(p) p不再指向这块空间的起始位置,
*p=i;
p++;
从某个位置开始中途释放是不行的
要释放这块空间必须从头开始,给起始位置的地址
一旦让指针变化移动就会有问题
4.5对同一块动态内存多次释放
4.6动态开辟内存忘记释放(内存泄漏)
return直接返回函数 free没有机会释放
这块空间的地址放到p里面了,一旦回到主函数都不知道这块空间在哪里,想释放都释放不了
只有等主函数彻底结束这块空间才会回收
这块空间不使用了,但我们又不能对它进行释放
如果程序一直不执行,这块空间就再也找不到了就会造成内存泄露
内存泄漏:一块空间申请走了用完了不使用了但没有释放,没有释放,别人也用不到这块空间,而自己又不释放;也有可能是再也没办法释放,找不到这块空间(等于消失了)
可以返回这个函数的地址,让后来者得到这个地址再释放
5.题目
5.1题目1
正确的改法:
1) 2)
5.2题目2
1)
int * f1(void)
{
int x=10;
return (&x); 返回栈空间地址的问题
} 一旦有人接收了它的地址得到的就是野指针
2)
int * f2 (void)
{
int * ptr;
*ptr=10; 没有初始化的指针怎么解引用?
return ptr; ptr是野指针
}
5.3题目3
存在内存泄漏的问题
没有free
改正:
加上free(str);
str=NULL;
5.4题目4
6.柔性数组
它不是单独的一个数组而是一个结构体里面的成员
结构体中最后一个元素允许是未知大小的数组,这就叫做柔性数组成员
1)在结构体中
2)最后一个成员
3)未知大小的数组
typedef struct st_type
{
int i;
int a[ ]; //柔性数组成员
}type_a;
6.1柔性数组的特点
1)结构体中的柔性数组成员前面必须有至少一个成员
2)sizeof返回的这种结构大小不包括柔性数组的内存
3)包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应大于结构的大小,以适应柔性数组的预期大小
6.2柔性数组的使用
1)
2)
前20个是1~20,后面的则是随机值
如果是以%x的形式
方法1)方便内存的释放;
连续的内存有益于提高访问速度,也有益于减少内存碎片