你管这破玩意叫指针?( 三 )


int p = &a;
用图来表示就是:

你管这破玩意叫指针?

文章插图
 
2. 指针变量本身的大小
视角放到这个变量 p 身上,虽然本质上这个变量 p 里面存放的就是一个数值,假设是 6,但是它却表示了一个内存地址的值 。
如果让程序员随便规定这个变量 p 的数据类型(也就是占多少个字节),那显然容易出问题 。
比如内存地址是 999,那么我用一个 char 类型的变量 p 来存放它,就会有问题 。
我们在编码阶段是无法确定一个变量的内存地址是多少的,所以用什么类型的变量来存放它,也是无法判断的 。
所以,最稳妥的办法就是,用一个完全能容纳所有内存地址范围的变量类型来存放指针变量 。
我们姑且认为我们是在一个 32 位的系统上,那么用一个 4 字节大小的变量来存放,就可以了 。(当然,实际上这取决于你的编译器的位数)
现在,我们的指针变量所占用的内存大小,就是固定的 4 个字节,也就是 4 个格子 。
【你管这破玩意叫指针?】程序员无需也无法修改这个大小,那么我们就可以把 p 前面的数据类型去掉了 。
short a = 1234;
p = &a;
3. 指针变量的类型
刚刚我们解决了指针变量本身所占用的内存大小,但是还有一个问题没有解决,就是指针变量里存放的内存地址处的变量的大小 。
也就是说,上面的指针变量 p 里虽然存放了变量 a 的内存地址 6,但是指针变量 p 却没有任何信息,来说明内存地址 6 处的变量,它的大小是多少 。
假如,我们认为内存地址 6 处的变量是个 char 类型,也就是只占用了一个字节,那么显然,会取出一个不符合预期的值 。
你管这破玩意叫指针?

文章插图
 
当然,如果认为 6 处的变量是个 int 类型,占 4 个字节,虽然数值上可能没有问题,但从某种程度上讲也是不太符合预期的(假如 8 号和 9 号格子里有其他内容,那就更不符合预期了) 。
你管这破玩意叫指针?

文章插图
 
所以,必须得完全按照变量本身的类型,也就是 short 类型来读取此内存地址处的值,才是正确的 。
那我们应该如何表示这个信息呢?即如何表示,变量 p 是一个指针,且这个指针里面存放的内存地址处的变量的类型是 short 。
很好办,直接说答案吧 。
short a = 1234;
short * p = &a;
p 前面的 * 表示变量 p 是一个指针类型,再前面的 short 表示该指针指向的内存地址处的变量,是个 short 类型的变量 。
当然,更准确的说法是,指针 p 将会按照 short 类型的变量来读取它指向的内存,至于那里到底是什么,无所谓 。
你管这破玩意叫指针?

文章插图
 
注意哦,这个 short 并不是表示指针变量本身的大小占 2 个字节,指针变量本身我们前面说过了,就是固定的 4 字节大小 。
不过总是这样说太绕口了,今后我们就说,变量 p 是个 short * 类型的指针,就可以了 。
用上面的图形象地说就是,右边变量 a 蓝色的填充,表示 a 是个 short 类型,而外面的虚线框框,表示指针 p 按照 short 类型的变量来"解读"内存地址 6 处的数值 。
两者相匹配了,就是"正确"的编程代码了 。
当然,这里的"正确",是说给程序员听的,CPU 才不关心 。
4. 指针所指向的值
上面我们已经可以获得某个变量的地址,比如获取 a 的地址就是:
&a
同时我们也可以定义一个指针变量,比如定义一个 short * 类型的指针变量 p:
short * p;
并且,我们通过直接赋值操作,可以给指针变量进行初始化:
p = &a;
当然,上面的代码也可以连起来写,即指针变量 p 的定义与初始化写在同一行:
short * p = &a;
不过,我们还没有一个方法,来表示指针变量 p 所指向的那块内存 。


推荐阅读