1.指针是什么
在理解指针是什么之前,我们首先要知道在计算CPU处理数据的时候,需要从内存中读取数据的,处理后的数据也会放回到内存中,那这些内存空间如何高效的管理呢?
其实是把内存分为一个一个的单元,每个单元的大小是一个字节,其中,每个单元中相当于一个八人间宿舍,每个人就是一个比特位,宿舍的房间号就是地址,而在计算机中房间号就相当于指针。
所以我们可以理解为:内存单元编号==地址==指针。
2.指针变量和地址
2.1取地址操作符(&)
在c语言中我们创建变量就是向内存申请空间,比如:
#include <stdio.h> int main() { int a = 10; return 0; }
上面代码中我们向内存申请了4个字节的空间,用来存放整数10,其中每个字节都是有地址的。那么我们怎样去得到这4个地址呢?
这里我们就需要学习一个操作符(&)--取地址操作符
#include <stdio.h> int main() { int a = 10; printf("%p ", &a); return 0; }
这里取出来的是a所占4个字节中最小的一个,所以另外三个字节我们也可以顺藤摸瓜得到
00D3FCC9,00D3FCCA,00D3FCCB
2.2指针变量和解引用操作符(*)
我们取出来的地址是一个数值,比如:00D3FCC8。这个数值有时候也是需要存储起来的,那么存储到哪里呢?答案就--指针变量。比如:
#include <stdio.h> int main() { int a = 10; printf("%p ", &a); int* p = &a; return 0; }
指针变量也是⼀种变量,这种变量就是用来存放地址的,存放在指针变量中的值都会理解为地址。
我们已经把a的地址给取出来放进指针变量p中了,那么当我们如何通过指针去对a里面存放的数据进行操作呢?这就需要我们再学习一个--解引用操作符(*)。比如:
2.3指针变量的大小
指针变量既然能够用来存放地址,那么说明它也是有大小的。
32位机器假设有32根地址总线,每根地址线出来的电信号转换成数字信号后是1或者0,那我们把32根地址线产生的2进制序列当做⼀个地址,那么⼀个地址就是32个bit位,需要4 个字节才能存储。
如果指针变量是用来存放地址的,那么指针变的大小就得是4个字节的空间才可以。
同理64位机器,假设有64根地址线,⼀个地址就是64个⼆进制位组成的⼆进制序列,存储起来就需要8个字节。
所以指针变量的大小跟它存放的数据以及本身的类型无关,只与平台环境有关。
3.指针变量的类型和意义
上面我们介绍的内容中只给出了整形的例子,那么如果我们想要创建一个指针变量来存放其他类型的数据其实也是一样的。比如:
字符型指针:char* p=地址
浮点型指针:flaot* p=地址
其中p只是指针名,可以是任意取的,去掉指针名之后就是指针的类型,比如:
字符型指针类型:char*
浮点型指针类型:flaot*
3.1指针的类型的意义
我们知道整形指针在32位平台下占4个字节,那么如果我们用字符指针去存放一个整形数据,再去利用指针去修改这个数据的时候,只能够修改一个字节,而如果用整形指针去存放,利用指针去修改数据的时候就修改4个字节。所以指针的类型决定了我们对指针进行修改数据和进行运算时能有多大的权限(⼀次能操作几个字节)。
3.2指针+-整数
我们先来看一段代码:
#include <stdio.h> int main() { int n = 10; char* pc = (char*)&n; int* pi = &n; printf("%p\n", &n); printf("%p\n", pc); printf("%p\n", pc + 1); printf("%p\n", pi); printf("%p\n", pi + 1); return 0; }
运行结果:
我们可以看到,对不同类型的指针进行+-相同的整数,他们+-的大小不一样,对char*类型指针变量跳过了一个字节,对int*类型指针变量跳过了4个字节,其实就是上面说过的,指针类型决定了指针向前或者向后走一步有多大(距离)。