C语言指针概述和运算
一、地址的含义、指针概念的提出
cpu在处理数据前,向地址总线发出状态,状态被内存接受,内存就会选中一个区域。根据CPU发出的动作,决定这个区域的数据是读是写。
想保存地址的数据,要解决哪些问题
-
容量够不够与cpu的寻址能力有关
32bit的cpu最大只能有2^32 = 4G的内存。一般来说,C语言直接操作的是OS,所以容量跟操作系统的位数有关。 -
找到此地址时,由于区域的最小单位是1B,而C语言(高级语言,不是汇编)提供了很多数据类型,所以操作这个区域,必须知道这个区域个数。
所以,他们首先提出了一种单独的新的类型,假设是pointer a
。但是这只能解决第1个问题,不能解决第二个,所以最后提出了这种:int *a
,用*
来提升这个变量为地址,同时用*
的外围指向第二个问题。
指针的概念
- 是数据类型,不过是一种特殊的数据类型。它有二元含义,一个是容量,一个是如何激活区域(即这区域有多少个)。
char *p1;
// p1是变量名,*把它升级为指针类型。*的左边是char,char回答了如何激活区域(激活多少个区域)
// p1的大小与前面的char没有任何关系,写int的还是一样,是与系统有关的,因为它存的是地址(地址是那个编号,也就是一串数字)。地址的大小永远只与位数有关。
// *p1的*前面有类型,那么这个*的作用是变量类型提升符;如果前面没有,那么*表示访问第一块元素,即*p1[0]
//*p1与p1[0]等价,[]的写法是偏移多少位
char *p1; // p1的名字提升为地址
char a[5]; // a的名字提升为数组名(常量)
*p1 // 以p1为首地址,访问第0个元素
p1[6] // 以p1为首地址,偏移6个元素的大小,访问对应的空间
char *s1[5]; // 有5个元素,每个元素存了“一把钥匙”
char (*s2)[5]; // 先升级为地址,5个char,5个char地访问
二、指针的运算
指针的运算的数学含义很弱,主要是逻辑的含义。
- 指针和数字
char *p1 = (char*)0x800000;
p1 + 1 //指加的一个单位,也就是`p1的首地址 + 1个单位的大小(sizeof(char))`
- 指针和指针
指针之间类型要一样,有不一样的,有的编译器会报错,有的会警告
int* p2 = (int *)0x800000;
int* p3 = (int *)0x80000C;
// 指针相减,是指针里面的地址相减,再除以数据类型的长度,可以用来算两个地址之间有多少个元素
p3 - p2 = (0x80000C - 0x800000) / sizeof(数据类型) = 3
三、指针是一种数据类型,数组是地址的常量
指针变量是映射关系,而数组则是相等关系(相当于别名)。
int data[5]; // 相当于下面这句
int *const data = 首地址;
&data // 非法使用,因为data和地址已经是相等的了,所以没有任何变量存了data等于的值的地址,所以取它的地址非法。最后是由编译器来定义行为