局部变量分配在栈中,该区域在windows平台默认为1M,
动态分配的内存在堆中,该区域非常大,在windows平台默认大于1.2G
使用动态内存的情况:1.需要通过变量定义数组 2.需要定义大容量的数组
创建动态内存:对内存的动态分配及释放时通过系统提供的库函数来实现的,主要有malloc,calloc,realloc,free这四个函数
怎样建立内存的动态分配:
1.malloc:函数原型 void *malloc(unsigned int size);
在内存的动态存储区中分配一个长度为size字节的连续空间 返回值为: 成功时:动态内存的首地址 失败时:NULL
malloc(100) 申请100字节的动态内存,注意函数的返回值为void *,即不指向任何特定类型的数据,只提供一个地址
如果此函数未能成功的执行(例如内存空间不足),则返回空指针(NULL)
2.calloc函数:其函数原型为void *calloc(unsigned n,unsigned size);
该函数会将内存的所有字节初始化为0,该函数完全可以被malloc替代
3.realloc:其函数原型为void *realloc(void *p,unsigned int size);
调整原申请的动态内存的大小,P是原动态内存的地址,size新的内存大小,以字节为单位。
必须接收新的返回值。
4.free函数:其函数原型为:void free(void *p);
释放指针变量p所指向的动态内存,
思考:为什么free函数不需要长度信息???参考:https://blog.csdn.net/caogenwangbaoqiang/article/details/79834150
申请内存块的时候,会有一种机制去记录内存块的大小,各个编译器的做法可能不同,比如申请的时候多分配4个字节,用来存储整个内存块的大小。所以在free()的时候只需要传指针,不需要传大小。
free释放的是指向指针的内存,内存!!!不是指针!指针是一个变量,在程序结束时才会被销毁,释放了内存空间后,原来指
向这块空间的内存还是存在,只不过现在指向的那块内容是垃圾,是未定义的,所以说是垃圾,
创建内存:
1.都是以字节为单位,注意乘以sizeof(类型)
2.realloc函数一定要接收返回值,不能使用原地址
free()崩溃的原因:
1.越界 2.移动指针指向 3.重复释放同一段内存
函数指针:函数的指针 如果在函数中定义了一个函数,在编译时,编译系统为函数代码分配一段存储空间,这段存储空间的起
始地址,称为这个函数的指针。
int (* p)(int ,int);
根据优先级p是一个指针,它指向一个函数,这个函数需要两个整型作为形参,一个整型作为返回值。
C语言规定:函数名本身也表示函数的地址,即Max等同&max
那么p=&max;可以写成p=Max;
那么(*p)(10,20);可以写成p(10,20);
变量和内存:
全局变量:定义在函数外面的变量,尽量少使用。
局部变量:定义在函数内部的变量,包括形参。
static:静态关键字,可以用来修饰全局变量,局部变量(不能修饰形参)和函数。
生命周期 | 作用域 | 默认值 | 内存区域 | 链接属性 | |
静态全局变量 |
程序运行时创建 程序退出时销毁 |
整个文件 | 0 | 全局(静态)变量区 | 内部的 |
普通全局变量 | 程序运行时创建程序退出时销毁 | 整个文件 | 0 | 全局(静态)变量区 | 外部的 |
静态局部变量 | 进入函数时创建程序退出时销毁 | 函数内部 | 0 | 全局(静态)变量区 | 无 |
普通局部变量 | 进入函数时创建函数结束时销毁 | 函数内部 | 随机值 | 栈 | 无 |
动态内存 | 调用创建函数创建,调用释放函数销毁 | 只要能获取指针的都能用 | 随机值 | 堆 | 无 |
静态函数 | 无 | 整个文件 | 无 | 代码段 | 内部的 |
普通函数 | 无 | 整个文件 | 无 | 代码段 | 外部的 |
代码段:存放程序的代码
全局(静态)变量区:存放全局变量和静态变量
栈:存放局部变量,系统自行管理该内存,内存区域小,windows默认1M
堆:动态内存区域,内存区域大,需要由程序自行管理内存,使用后一定要释放,否则出现内存泄漏。
例:请说明下面的指针分别指向什么位置:
&p: A ,p: B &p1: C ,p1: C
&p2: C ,p3: D ,p4: C p5: A
void foo(char a)
{
static char nCount;
char p1[]="AAA";
char *p2="AAA";
char *p3=(char *)malloc(10);
char *p4=&a;
char *p5=&nCount;
}
void *p (char)=foo;
A:数据段(全局变量区) B:代码段 C:栈 D:堆 E:不一定,视调用情况而定