1.内存和存储
在计算机中最小的信息单位是bit,即一个二进制位。
8个bit组成一个Byte,也就是一个字节。
一个内存单元可以存储一个Byte,也就是一个字节。
cpu在访问内存单元的时候要给出内存的地址。
一、指针变量
在c语言中,我们创建了一个变量,用于存储内存地址,这个变量就是指针变量。
当我们在c语言中,创建了一个变量,如何获取它的地址,我们就用——&取地址符号。
接下来,我们演示一下创建一个a,获取它的地址并且输出。
这里我们用%p来打印地址,&用来取出a的地址。
此处我们可以看到a的地址是0000009ACD6FF684.
这里我们打开vs的内存窗口看看a的地址。
我们可以看到a的地址就是0x0000009ACD6FF684.
我们可以看到在a的地址处存放了一个3.
有时候,我们在后期会用个某个量的地址,那么我们怎么办把地址存储起来方便后期使用?——用指针变量。
还是用上面的变量a,我们再创建一个指针变量负责保存a的地址。
我们将a的地址通过取地址符&取出来放到p中,由于p的值为地址,所以在打印时需要用到%p,接着你可能注意到,在打印p的值的时候,我们没有用上&,因为我们只需要打印p里面存放的值。我们要将p和&p区分开来。
如图所示,当我们打印p的值时,其实是打印p里面存储的a的地址,也就是000000AEDE3AF994。
当我们打印&p时,其实是打印p自己本身的地址,也就是0000008C479BF898.
(1)指针变量的类型
int *p=&a;
这条语句我们来做个拆分理解:
int 指的是p所指的内容是int类型。
*,解引用操作符,说明了p是个指针变量。
int *合起来就是p的类型。
(2)*解引用操作符
我们可以想象指针变量是一个任意门,任意门上写的是任意门通往的神秘地方的地址,当你用钥匙打开任意门,里面就是那个神秘地方的内容。而那个🔑就是*,也就是解引用操作符。
我们也可以认为*p与a相等。
解引用操作符,就是将指针变量所指向的地址上存储的值取出来。
(3)指针变量的大小
这里有一件值得注意的事情
我们都知道int类型的变量是4个字节大小,char类型的变量是1个字节的大小,那么指针变量的大小是多少呢?
我们用vs试一下:
1.x86平台,也就是32位平台下
我们发现指针变量的大小是4.
2.64位平台下
在64位平台下,指针变量的大小又变成了8。
还需注意的一点是,在相同的平台,int *类型的指针变量大小和char *指针变量的大小是相同的。
64位:
32位:
(4)不同类型的指针变量的区别
既然指针变量的大小一样,那不同类型的指针变量的区别在哪呢?
让我们来对比一下int*类型的指针和char*类型的指针变量
首先是int*类型:
*p1=0;语句执行前,我们可以看到n的内存中放的是44 33 22 11.
语句执行后
这时我们发现n的4个字节全部变成了0.
再来看看char*类型:
*p2=0;语句执行前,我们可以看到n的内存中放的是44 33 22 11.
语句执行后:我们可以看到n内存中的一个低位字节44被改成了00.
由此我们可以看出不同类型的指针变量之间的区别。
指针变量的类型决定了指针解引用时一次性能访问多少个字节。
二、指针运算
(1)首先是指针+-整数
我们来几个例子看看
我们可以看到int*类型的指针+1,就跳过了一个元素,而int类型的数组,一个元素就是一个int类型的大小,即四个字节。也就是说,p+1跳过了四个字节。
我们再来看看char*类型的指针+1
此时p+1后,还是跳过一个char类型的元素,而一个char类型的元素的大小是1个字节。
不难发现,指针变量+-1一次跳过几个字节,却决于指针指向的数据类型。
(2)指针-指针
指针-指针的出来是两个指针之间元素的个数,如何去理解呢,请看图片!
p2中所装的地址如下:
p1中所装的地址如下:
p2-p1得出来应该是-12,又因为p2和p1都是整型,整型大小为4个字节,-12/4=-3,这个3就是p2和p1之间元素得个数。
此时运行我们的程序:
走~
(3)指针的关系运算
当两个指针指向相关的变量,比如一个数组里面的两个元素。这时候我们可以对这两个变量进行大小比较。
三、空指针
void*类型的指针变量可以用来接受任意类型的地址,这个在我们要接受多种数据类型的地址时非常好用。但是有一点很重要,那就是空指针不能进行指针运算。
为什么不能对空指针进行+-运算呢?
首先我们刚刚知道,指针的+-运算要靠指针所指向的变量的类型来判断加减几个字节。当指针变量类型为void*,这时指针变量无法得知自己加减几个字节。
四、野指针
关于它的定义,我们有请百度百科:
这时我们已经对野指针有了初步认识,要注意的是,出现野指针在我们写代码的过程中是有很大危险的。那么如何去规避它呢?
1.给指针初始化,如果还为确定指针应该指向什么样的地址,那么我们可以给野指针赋值为NULL。
2.当不再使用指针时,给指针赋值为NULL。在使用指针前,检查指针是否为NULL。
3。不要返回局部变量的地址。
对于指针的初步学习,我们就到这里,如果你还想进一步了解指针,请关注我后面的文章。
若这篇文章有帮助到你,请留下您珍贵的点赞、收藏+评论,这对于我将是莫大的鼓励!学海无涯,共勉!