一、内存的结构
哈佛结构:数据和代码分开存放。
冯诺依曼结构:数据和代码放在一起。
动态内存和静态内存:动态内存需要初始化之后才能使用,静态内存不需要初始化就可以使用,读写速度较快。
内存编程模型:内存可以想象成一个个排列的单元格,每个单元格都有其特定的地址,且永久绑定,内存地址理论上可以有无限大,但是受制于CPU的位数,32位的CPU的内存地址范围最大为2的32次方,也就是4G的内存,64位的CPU则可以有2的64次方的内存地址范围。
1.1 栈
栈的概念:栈是在C语言中的一种数据结构,用于管理内存,可以自动的帮助我们分配一些小块内存,栈具有先入后出的特性,栈低指针始终指向栈的开始,栈顶指针可以进行上下移动,向栈中压栈数据时栈顶指针向上移动一位。
栈的约束:栈是有固定大小的,栈的大小不好设置,太小怕溢出,太大怕浪费,所以栈不够灵活,在局部变量定义过多或者过大时,或者递归层级过多时,就有可能造成栈溢出。
1.2 堆
堆的概念:堆是内存的另外一种管理方式,堆管理没存比较自由,可以随时申请和释放,内存的大小可以根据需要自定义,操作系统通常把内存划分区块,把一部分内存区域分配给堆来管理,堆内存并不属于某一个进程,由堆管理器进行管理,进程调用堆管理器提供的内存管理API(malloc和free)来分配和释放内存。当系统收到程序的申请时,会遍历记录空闲内存地址的链表,以求寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,此处应该注意的是有些情况下,新申请的内存块的首地址记录本次分配的内存块大小,这样在delete尤其是delete[]时就能正确的释放内存空间。
堆的内存特点:
- 堆内存通常不限于容量。
- 申请和释放都需要程序员手工进行,在程序代。码中调用malloc以及free函数进行内存分配和释放,如果申请了内存没有释放,则该段内存丢失,会造成内存泄露
- 堆内存比较灵活,空间大小可以随意控制,但是由于过于灵活,需要程序员处理的细节较多,所以容易出错。
1.3 BOSS段
通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。
1.4 数据段
数据段(data segment)通常是指用来存放程序中 已初始化 的 全局变量 的一块内存区域。数据段属于静态内存分配。
1.5 代码段
代码段(code segment/text segment)通常是指用来存放 程序执行代码 的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于 只读 , 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些 只读的常数变量 ,例如字符串常量等。程序段为程序代码在内存中的映射.一个程序可以在内存中多有个副本。
C语言中内存空间分配
int a = 0; //全局初始化区
char *p1; //全局未初始化区
int main()
{
int b; // 栈
char s[] = "abc"; //栈
char *p2; //栈
char *p3 = "123456"; //123456\0在常量区,而p3在栈上。
static int c =0; //全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
return 0;
}