1、内存编址:
内存在逻辑上就是一个一个的格子,这些格子可以用来装东西(里面装的东西就是内存中存储的数),
每个格子有个编号,这个编号就是内存地址。
内存地址和格子空间一一对应且永久绑定。(参见内存初探(1))
在程序运行时,计算机中CPU实际只认识内存地址,而不关心这个地址所代表的空间在哪里,怎么分布这些实体问题。
因为硬件设计就保证了按照这个地址就一定能找到这个格子,
所以说内存单元有2个概念:
地址 和 空间
2、内存编制的关键:
内存编址是以字节为单位的(8bit)。
3、内存与数据类型的关系:
C语言中基本的数据类型有:int(4)char(1)short int(2)long(4)float (4)double(8)---------------64位下的。
那unsigned 这个关键字呢,也就是有符号与无符号占用的空间是什么样的呢?
其实呀,有符号数与无符号数占用的空间是一样的。
比如说char与unsigned char都是占用1个字节,它们的区别是,若定义成有符号,则所占用空间的最高位用来表示符号,0为正,1为负。
也正因为如此,char表示的范围是-127~127,而unsigned char则是0~255。
再换种说法,因为定义成有符号,最高位被用于识别符号,也就是有效的数据位只有7位,也就是最大只能表示127,加上符号那就是它的范围-127~127了,
那么无符号也类似,8位有效的位最大可以表示255,所以范围就是0~255。
4、内存对齐:
#include <iostream> using namespace std; struct X1 { int i;//4个字节 char c1;//1个字节 char c2;//1个字节 }; struct X2 { char c1;//1个字节 int i;//4个字节 char c2;//1个字节 }; struct X3 { char c1;//1个字节 char c2;//1个字节 int i;//4个字节 }; int main() { cout<<"long "<<sizeof(long)<<"\n"; cout<<"float "<<sizeof(float)<<"\n"; cout<<"int "<<sizeof(int)<<"\n"; cout<<"char "<<sizeof(char)<<"\n"; X1 x1; X2 x2; X3 x3; cout<<"x1 的大小 "<<sizeof(x1)<<"\n"; cout<<"x2 的大小 "<<sizeof(x2)<<"\n"; cout<<"x3 的大小 "<<sizeof(x3)<<"\n"; return 0; }

5、C语言如何操作内存:(用变量名来访问内存,数据类型的含义,函数名的含义)
(1)C语言对内存地址的封装
例如:int a;
a = 5;
a += 4;//a == 9;
结合内存解析本质:
int a;//编译器帮我们申请了1个int 类型的内存格子(长度是4字节,地址是确定的,但是只有编译器知道在哪,我们不知道,也不需要知道)
a = 5;//编译器知道我们要给a赋值,就会把数值5丢给符号a绑定的那个内存格子里。
a += 4;//编译器发现要给a加值,就会把a原来的值读出来,然后给这个值加上4,在把加好之后的值写到a里面去。
(2)C语言中数据类型的本质含义是:表示一个内存格子的长度和解析方法。
数据类型决定长度的含义:我们一个内存地址(0x30000000),本来这个地址只代表1个字节的长度,但是实际上我们可以通过给他一个类型(int),让他有了长度(4),这样这个代表内存地址的数字(0x30000000)就能表示从这个数字(0x30000001)开头的连续的n(4)个字节的内存格子(0x30000000 + 0x30000001 + 0x30000002 + 0x30000003)。
数据类型决定解析方法的含义:例如我有个地址(0x30000000),我们可以通过给这个内存地址不同的类型来指定这个内存单元格子中二进制数的解析方法。换而言之,
(int)0x30000001,含义就是(0x30000000 + 0x30000001 + 0x30000002 + 0x30000003)这4个字节连起来共同存储的是一个int 型数据;
(float)0x30000001,含义就是(0x30000000 + 0x30000001 + 0x30000002 + 0x30000003)这4个字节连起来共同存储的是一个float 型数据;
(int *) 0;
(float *) 0;
(short) 0;
(char) 0;
int a; //int a;时编译器会自动给a分配一个内存地址,例如0x12345678
(int *) a; //等价于(int *)0x12345678
(float *) a;
(3)C语言中,函数就是一段代码的封装。函数名的本质就是一个内存地址。
6、用指针来间接访问内存:
关于类型(不管是普通变量 int float 等,还是指针类型int * ,float *等),只要记住:
类型只是对后面数字或者符号(代表的是内存地址)所表征的内存的一种长度规定和解析方法规定而已。
C语言中的指针,全名叫指针变量,指针变量和普通变量没有任何区别。
例如:int a; 和 int *p; 其中 a 和 p 都代表一个内存地址(0x20000000),但这个内存地址(0x0000000)的长度和解析方式不同。
a是int 型,所以a的长度是4字节,解析方式按照int来规定;
p是int * 型,所以长度4字节(指针的长度都是4字节),解析方式是int *(0x20000000开头的连续4字节中存储了1个地址,这个地址所代表的内存单元中存放的是一个int型的数。)
7、用数组来管理内存:
**(普通变量,数组,指针变量 的区别就是对内存地址的解析方式不同)
int a; //编译器分配4个字节长度给a,并且把首地址和符号a绑定。
int b[10]; //编译器分配40个字节长度给b,并且把首元素首地址和符号b绑定起来
数组中第一个元素(a[0])就称为首元素:每一个元素类型都是int,所以长度都是4。
(a[0] 的地址)就成为首元素首地址。
浙公网安备 33010602011771号