第10章 指针
指针是C语言的一个重要组成部分,是C语言的核心、精髓所在。用好指针,可以在C语言开发中起到事半功倍的效果。一方面,可以提高程序的编译效率、执行速度,以及动态存储分配;另一方面,可使程序更加灵活,表示和操作各种数据结构更便捷,编写出高质量的应用程序。本章的知识架构及重难点如下:![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/f4e20eaa276842cb858064652fabaff1.png#pic_center)
10.1 指针的相关概念
指针是C语言的独特之处,其使用起来十分灵活。使用得当,能显著提高某些程序的效率;使用不当,则很容易造成系统错误。许多程序“挂死”往往都是错误地使用指针造成的。
10.1.1 地址与指针
要想弄明白什么是指针,就必须弄清楚数据在内存中是如何存储的,又是如何被读取的。
通常来说,系统会按字节对每个内存单元进行编号,这些内存单元就好比是许多带有编号的小房间,要想使用内存,就需要知道房间编号。例如,定义一个整型变量i需要4个字节,编译器就会为其分配4个内存单元,如图10.1所示,1000~1003就是对应变量i的4个内存单元地址,其内存放的数值是0。假设又定义了一个整型变量j,则j在内存中的起始地址是1004,因为j同样占4个字节,所以1004~1007单元中保存的是j,其值是1。同理,1008~1012、1012~1016、1016~1020也同样是3个整型变量对应的内存空间,如图10.2所示。可见,编译系统为每个变量都分配了一个能满足其类型大小的内存单元地址,访问该地址就能找到对应变量。那么,程序设计中,又该如何访问变量的地址呢?前面我们学习过取地址符“&”,其作用是获取变量在内存中的地址。例如,&i表示变量i的内存起始地址1000。通过&i可以访问变量i指向的内存单元,进而读取变量i。如图10.3所示,“指向”某个变量地址用箭头表示,就好像旅店住宿时某个房间号牌指向某个房间一样。![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/3aae38d6428a405b9ece5b93c0712604.png#pic_center)
为了好记忆,我们将变量的地址形象化地称为该变量的“指针”,意思是通过它能访问以它为地址的内存单元。例如,通过地址1000可以访问变量i的地址,进而读取4个字节得到i的值。
10.1.2 变量与指针
变量的地址是变量和指针之间的连接纽带。所谓“指向”,是通过地址来体现的。因为指针变量通常指向一个变量的地址,所以将一个变量的地址赋给指针变量后,这个指针变量就“指向”了该变量。例如,将变量i的地址&i存放到指针变量p中,p就指向i,其关系如图10.4所示。![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a0f16b11efcf43a2ae369b001d74a6aa.png#pic_center)
程序代码中一般通过变量名对内存单元进行存取操作,但代码编译后,会将变量名转换为该变量在内存中的存放地址,后续对变量值的存取都是通过该地址进行的。例如,对图10.2中的变量i和变量j进行如下求和操作:
i+j;
计算机内部的存取流程是:根据变量名与地址的对应关系,找到变量i的地址1000,然后从1000开始读取4个字节数据放到CPU寄存器中,再找到变量j的地址1004,从1004开始读取4个字节的数据放到CPU的另一个寄存器中,通过CPU的加法中断计算出结果。
低级语言(如汇编语言)中一般直接通过地址来访问内存单元,高级语言中一般使用变量名来访问内存单元。C语言作为高级语言,仍然提供了通过地址来访问内存单元的方式。
10.1.3 指针变量
一个变量的地址称为该变量的指针。如果有一个变量专门用来存放另一个变量的地址,它就是指针变量。在C语言中有专门用来存放内存单元地址的变量类型,即指针类型。
1.指针变量的定义
定义指针变量的一般形式如下:
类型说明 * 变量名
其中,“*”表示该变量是一个指针变量,“变量名”即为定义的指针变量名,“类型说明”表示本指针变量所指向的变量的数据类型。
2.指针变量的赋值
指针变量同普通变量一样,使用前需要先进行定义并赋予具体的值。未经赋值的指针变量不能使用。与其他变量赋值不同,给指针变量赋值只能赋予地址,而不能是其他数据,否则将引起错误。C语言一般用“&变量名“表示某个变量的地址,如&a表示变量a的地址,&b表示变量b的地址。给一个指针变量赋值可以有以下两种方法。**(1)定义指针变量的同时进行赋值。例如:**
int a;
int *p=&a;
(2) 先定义指针变量,之后再赋值。例如:
int a;
int *p;
p=&a;
注意:
注意这两种赋值语句的区别。如果先定义指针变量之后再赋值,赋值时指针变量前不再加"*"。
【例10.1】输出某个数的地址 从键盘中输入一个数,利用指针将这个数的地址以十六进制形式输出。实现代码如下: