------------------- 数组
| 程序栈 |----------高地址--〉低地址函数
-------------------spa
| 堆 |----------向上增加指针
-------------------进程
| BSS |----------数据段ip
| 全局和静态变量 |内存
------------------- ----------低地址字符串
| 可执行代码 |----------代码段terminal
-------------------class
可执行指令放在代码段中,任什么时候刻,内存中只有一份相同程序的指令拷贝,多个实例共享这些代码。
初始化为非零的静态数据和全局数据存放在数据段中,运行相同程序的每一个进程,有本身的数据段。
初始化为零的全局数据和静态分配数据存放在进程的BSS区域中,每一个运行的进程都有本身的BSS,程序运行的时候,将数据放到数据段中,由此可知,只有初 始化为非零的变量才占用空间,因此对于相似static int ss[1024];这样的数组自动用0来填充,它占的空间很小。
堆,动态内存来自于堆,即:经过malloc获得的空间,一般状况下,堆是向上增加的,即:后面分配的地址比前面的地址在数值上大一些。
栈,分配本地变量的地方,函数参数、函数的返回值和返回地址也放在栈空间中,须要特别注意的是,当函数返回后,存储在栈空间中的函数变量“自动消失”,空间被其余函数使用。栈空间是向下增加的。
在C语言中,通常经过malloc/calloc函数分配空间,经过free()函数释放空间,使用realloc()改变已分配空间的大小。
分配内存的步骤:
1.申明一个指定类型的指针
2.计算要分配空间的大小,通常使用函数sizeof()来实现
3.调用函数malloc()完成空间的申请,将函数的返回值赋给指针变量,
4.检查返回值是否不为NULL,保证空间分配成功
5.分配好的空间是没有通过初始化的,其中可能包含一些垃圾信息,所以
调用函数memset()将其用0来填充是个好的习惯
释放内存步骤:
1.调用函数free()释放掉空间
注意:1.不可使用free()掉后的空间
2.free()后,最好将指针置为NULL,由于若是不作这步处理,
原来的指针依旧指向刚才释放的空间,能够继续操做
3.避免重复释放空间
在Unix系统上,提供了函数alloca()函数,能够实如今栈空间上分配指定大小的空间,这样的好处是,函数结束后,空间自动释放,没必要显式地调用函数free(),可是该函数有不少弊端,好比不可移植等,所以不建议使用。
有必要提一下malloc、calloc、realloc函数的底层实现,在Linux系统中,提供了brk()和sbrk()函数,上面几个函数就是在这两个函数的基础上实现的。
int *p = (int*)malloc(20);//动态在堆区分配空间,(空间内容初始值为随机值)必须人为释放
//free(p);;
int *p2 = (int*)alloca(20);//动态在栈区分配空间(空间内容初始值为随机值),自动释放。
int *p3 = (int *)calloc(4,5);//动态在堆区分配空间,(空间内容初始值为0)必须人为释放
free(p3); p3 = NULL;
int *p4 = (int*)realloc(p,30);////动态在堆区扩充内存空间,(空间内容初始值为随机值)必须人为释放
free(p4); p4 = NULL;
char *p5 = "hello";
char *p6 = "hello";
*p5 == *p6 由于 "hello" 是字符串常量,定义后会在常量去开辟一块空间存储hello,
由于是在常量区不可修改,因此不必再重新申请一块新空间去存储另外一个"hello",因此,
p5,p6指的是一块区域.
char p7[] = "hello";
char p8[] = "hello";
就彻底不同了,由于这是在栈区申请的区域,因此是不一样的两块空间.