C语言如何操作内存
1、用变量名来访问内存(c语言对内存地址的封装、数据类型、函数名)--直接访问内存(使用地址)
如 int a; 编译器将申请32bit的内存(4个内存单元),同时将内存地址和变量名a绑定,操作a时,编译器根据a绑定的地址去寻找对应的内存单元,我们则无需再关注具体的内存地址了。所以变量名被编译器绑定上了地址。
数据类型:表示一个内存格子的长度和解析方法。(内存编址的单位是一个字节)
(int *) 0; //0的地址存的是指针,指针指向一个int类型的数,数据类型int规定了内存格子长度:4字节
(float *) 0; //0的地址存的是指针,指针指向一个float类型的数
(short ) 0; //0地址是short类型的变量,存的是short类型的数
(char ) 0; //0地址是char类型变量,存的是char类型的数
这四个只是类型不同,但都是0,0代表内存地址(人为指定的)。数据类型只是决定了长度,存的内容(解析方法)。
数据类型决定长度的含义:我们一个内存地址(0x30000000),本来这个地址只代表1个字节的长度,但是实际上我们可以通过给他一个类型(int),让他有了长度(4),这样这个代表内存地址的数字(0x30000000)就能表示从这个数字(0x30000000)开头的连续的n(4)个字节的内存格子了(0x30000000 + 0x30000001 + 0x30000002 + 0x30000003)。
数据类型决定解析方法的含义:譬如我有一个内存地址(0x30000000),我们可以通过给这个内存地址不同的类型来指定这个内存单元格子中二进制数的解析方法。譬如我 (int)0x30000000,含义就是(0x30000000 + 0x30000001 + 0x30000002 + 0x30000003)这4个字节连起来共同存储的是一个int型数据;那么我(float)0x30000000,含义就是(0x30000000 + 0x30000001 + 0x30000002 + 0x30000003)这4个字节连起来共同存储的是一个float型数据;
解析方法举例:假设内存里存着 int a;float a;都存着 0x1111 0101 1101 1011,解析的时候int可能从第一位就开始判断符号位,之后的位数都代表数值,而float可能从第一位后面断开,前面当做符号位,后面作小数位,具体的解析方法忘记了,大概理就是这样,具体的解析方法可以看计算机组成原理。内容相同,解析方法不同而已。
对数据类型强制转换的理解:
int a = 1;
(float)a;
其实地址a开头的连续4个内存单元格中,其存储的内容没变,还是1对应的2进制,但是本来是以int方式解析的,现在被强制转换成以float方式解析,如果是(short)a;就是short类型解析以a开头的连续2个内存单元,对另外两个内存单元不作解析
函数名含义:函数本身就是一段代码的封装,函数名的含义是一段代码的首地址,本质就是内存地址。
2、用指针间接访问内存
关于类型(不管是普通变量类型int float等,还是指针类型int * float *等),只要记住:
类型只是对后面数字或者符号(代表的是内存地址)所表征的内存的一种长度规定和解析方法规定而已。
int a; // int a;时编译器会自动给a分配一个内存地址,譬如说是0x12345678
(int *)a; // 等价于(int *)0x12345678 对其中内容
(float *)a; //解析方法是以指针来解析的
C语言中的指针,全名叫指针变量,指针变量其实很普通变量没有任何区别。譬如int a和int *p其实没有任何区别,a和p都代表一个内存地址(譬如是0x20000000),但是这个内存地址(0x20000000)的长度和解析方法不同。a是int型所以a的长度是4字节,解析方法是按照int的规定来的;p是int *类型,所以长度是4字节,解析方法是int *的规定来的(0x20000000开头的连续4字节中存储了1个地址,这个地址所代表的内存单元中存放的是一个int类型的数)。
3、数组管理内存:
数组管理内存和变量其实没有本质区别,只是符号的解析方法不同。(普通变量、数组、指针变量其实都没有本质差别,都是对内存地址的解析,只是解析方法不一样)。
int a; // 编译器分配4字节长度给a,并且把首地址和符号a绑定起来。
int b[10]; // 编译器分配40个字节长度给b,并且把首元素首地址和符号b绑定起来。