论指针中需要认真辨识的3组概念
2020-10-21赖玲
赖玲
摘 要:通过对指针中3组容易混淆的概念研究,介绍了它们的辨识方法,以具体实例为依据,介绍了对数据加工和处理的方法,有助于夯实编程基础,促进编程能力的提高.
关键词:指针;地址;数组;函数
中图分类号:TP312 文献标识码:A 文章编号:1673-260X(2020)03-0022-03
指针是C语言中的一个重要概念,是其最具特色的部分,是C语言的精华,同时也是C语言的难点.指针除了能动态地分配地址,表示复杂的数据结构,在调用函数的时候能够得到1个以上的结果外,在系统软件的设计也是非常重要的.笔者在实际的教学和学生的实际编程指导中发现,很多学生对“指针变量的定义符”和“指针变量的取值运算符”“指针函数”和“函数指针”“指针数组与数组指针”等概念混淆不清;认真辨识有关概念,砺清它们间的相互关系,对于编制简洁、紧凑、高效的应用程序非常有用,下面谈谈应该辨识的几个概念.
1 “指针变量的定义符”和“指针变量的取值运算符”
操作符“*”既可以用来作为指针变量的定义符,也可以用作指针变量的取值运算符.要根据“*”操作符出现的位置进行判断.
例1 int i=3, *p;
p=&i;
printf("%d",*p);
scanf("%d",p);
*p=5;
程序的第一句“int i=3;*p;”定義了一个整型变量i和一个整型的指针变量p,i里面只能存放整型变量的值,p(这里P前面的操作符“*”就是指针变量的定义符)里面只能存放整型变量的地址,i的初始值为3,执行“p=&i;”中的“&”是取地址操作符,“p=&i;”将i的地址存到指针变量p的空间里面,也可以理解为将指针变量p指向整型变量i的首地址,见图1所示.
程序中的第三句,以十进制整数的形式输出*p,对于*p理解十分重要,这里p前面的操作符“*”就是取值运算符,就是p当前所指向变量i的存储空间里面存放的内容3.第四句是向指针变量p所指向的空间输入十进制整型数据,等价于scanf("%d",&a),第五句是用5覆盖指针变量p所指存储空间里面的内容,等价于“i=5;”,因为p是指向整型变量i的首地址,“*p=5;”就是将p当前所指向变量i的存储空间里面的内容修改为5,这是间接寻址方式.
这里辨识的原则:一级指针变量中存放目标变量的地址,凡是在声明的语句中出现的操作符“*”是指针变量定义符,如例1程序第1行中的操作符“*”;在操作和控制部分出现的操作符“*”就是取值运算符,如例1程序第3行和第5行中的操作符“*”.
对于取值的理解一定要注意取值的内容,对于一级指针,取得内容为“指针所指向存储空间里面的内容”即存储空间的值,对于二级指针或者多级指针有“取存储空间的地址”和“取存储空间里面的内容”的区别.
例2 int a,*p,**pp;
a=22;
p=&a;
pp=&p;
printf("%p,%d",*pp, **pp);
假设变量a的地址为4000,指针p的地址为4100,二级指针pp的地址为4800,a、p、pp三者的关系如图2所示.
由图2可以看出,a的地址为4000,保存在指针变量p中,p指向a,p的地址为4100,保存在pp中,即二级指针pp指向指针变量p,此时,要引用a的值,可以使用*p,也可以使用**pp.注意:虽然p、pp都是指针变量,但p和pp指向的内容有着本质上的不同,p指向的是普通变量的地址,pp只能指向指针变量的地址而不能指向普通变量的地址.
也就是说,二级指针的指针变量中存放的是一级指针变量的地址,对于指针变量的定义符和一级指针一样,只要是在声明语句中出现的操作符“*”都是指针变量的定义符,例2中第1行中的操作符“*”和操作符“**”都是指针变量的定义符,第5行“printf("%p,%d",*pp,**pp);”中“*pp”的“*”和“**pp”前面的“*”是指针变量取值运算符,只不过它们取值的内容不一样,“*pp”取的是目标对象的地址,“**pp”也就是“*(*pp)”,取的是目标对象的内容.
2 “指针数组”与“数组指针”
2.1 “指针数组”
对于给定的一个数组,其元素都是存放同一类型数据的地址,这样的数组称为“指针数组”. “指针数组”其本质为数组,只不过数组元素是同一类型数据的地址.例如:
int *p[4];
这里定义了一个指针数组,该数组的每个元素是整形变量的地址.对于“*p[4]”可以这样理解,由于“[ ]”操作符比“*”操作符的优先级高,因此p先与操作符“[ ]”结合,形成p[4]形式,这显然是数组的形式,表示p数组里面有4个元素,p[4]中的p再与前面的操作符“*”结合,“*”是指针类型定义符,表示此数组是个指针类型,每个数组元素都可以指向一个整型变量.*p[i]相当于*(p[i]),都表示下标为i元素的地址,因为操作符“[ ]”优先级高于操作符“*”.
注意:这里提到的优先级,操作符“()”高于操作符“[ ]”高于操作符“*”.
2.2 “数组指针”
“数组指针”也称为行指针,是指向数组地址的指针,其本质为指针.其定义形式为:
(*指针变量名)[长度]
例如:int (*P)[n]
这里操作符“()”的优先级比操作符“[ ]”优先级高,“(*P)”表示是个指针,再与操作符“[ ]”结合,表示“数组指针”,“长度”表示二维数组分解为多个一维数组时,一维数组的长度,也就是二维数组的列数.
例3
main()
{int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int *q,(*p)[4];