一.什么是内存
内存是存储颗粒的集合,最小的内存单位可以用来存储0和1的存储状态,内存是用来存储可变数据的。
二.内存的基本单位
内存单元的存储单位有4个,位(1bit) 字节(8bit) 半字(一般是16bit) 字,一字节等于八位,一位等于1bit。
三.内存对齐
为了提高效率
1 #include<iostream>
2 using namespace std;
3
4 struct A
5 {
6 char a;
7 short b;
8 int c;
9 };
10
11 struct B
12 {
13 short b;
14 int c;
15 char a;
16 };
17
18 int main()
19 {
20 cout<<sizeof(A)<<endl; //8
21 cout<<sizeof(B)<<endl; //12
22
23 return 0;
24 }
四.C语言对内存的访问与解析
例子:
1 譬如在C语言中, int a; a = 5; a += 4; // a == 9;
int a; // 编译器帮我们申请了1个int类型的内存格子,长度是4字节,地址是确定的,并且把符号a和这个格子绑定。
a = 5; // 编译器发现我们要给a赋值,就会把5丢到符号a绑定的那个内存格子中。
a += 4; // 编译器发现我们要给a加值,编译器会先把a原来的值读出来,然后给这个值加4,再把加之后的和写入a里面去。
五.动态内存和静态内存
静态内存是指在程序开始运行时由编译器分配的内存,当该变量在作用域内使用完毕时,系统会自动释放所占用的内存空间,都无须程序员自行考虑。比如定义数组…。
动态内存是程序员自己确定使用内存空间大小,或者空间太大,栈上无法分配时,会采用动态内存分配,常用malloc申请,用完用free释放。
六.管理内存的数据结构
数组:
1 int b[10]; // 编译器分配40个字节长度给b,并且把首元素首地址和符号b绑定起来。
- 数组定义时必须同时给出数组元素个数(数组大小),而且一旦定义再无法更改。
- 数组中第一个元素(b[0])就称为首元素;每一个元素类型都是int,所以长度都是4,其中第一个字节的地址就称为首地址;首元素b[0]的首地址就称为首元素首地址。
结构体:
结构体发明出来就是为了数组中所有元素类型必须相同的缺陷,结构体中可以有不同类型的数据。
1 struct people
2 {
3 int age; // 人的年龄
4 char name[20]; // 人的姓名
5 int height; // 人的身高
6 };
7
8 因为people的各个元素类型不完全相同,所以必须用结构体,没法用数组。
栈(stack),队列:
1 先进后出 FILO first in last out 栈 (类似一个只有一个开口的瓶子)
2 先进先出 FIFO first in first out 队列 (类似一段水管)
栈的优点:分配和最后回收都不用程序员操心,C语言自动完成。
栈的约束:预定栈大小不灵活,怕溢出。
堆:
C语言操作堆内存的接口(malloc free)
堆这种内存管理方式特点就是自由(随时申请、释放;大小块随意)。
如果程序员申请内存并使用后未释放,这段内存就丢失了,称为内存泄漏。
七.C语言为内存分配空间
代码段:对应着程序中的代码(函数),代码段在linux中又叫文本段(.text)。
数据段(data段):显式初始化为非0的全局变量,显式初始化为非0的static局部变量。
bss段存:显式初始化为0的全局变量,显式初始化为0的static局部变量。
堆:用的时候自己申请,自己使用,完了自己释放。
栈:栈内存区,局部变量分配在栈上;函数调用传参过程也会用到栈,递归函数运行也在栈上。
文件映射区:文件映射区就是进程打开了文件后,将这个文件的内容从硬盘读到进程的文件映射区,以后就直接在内存中操作这个文件,读写完了后在保存时再将内存中的文件写到硬盘中去。
内核映射区:内核映射区就是将操作系统内核程序映射到这个区域了。
八.变量的生命周期
栈:局部变量(栈变量)存储在栈上,代码执行过程中按照需要去创建、使用、消亡的。
堆:从malloc申请时诞生,然后使用,直到free时消亡。
数据段、bss段:程序被执行时诞生,在程序终止时消亡。
代码段、只读段:生命周期是永久的。