浅谈C语言指针变量的“地址”与“值”

2020-03-11 11:35
福建质量管理 2020年5期
关键词:数组指针C语言

(重庆三峡学院计算机科学与工程学院 重庆 404100)

C语言指针数据类型是整个C语言教学的重点难点。指针这个词是从英文单词 “pointer”直译而来,事实上,指针更应该翻译为地址,指针变量称之为地址变量更合适。由于指针数据类型的存在,使得C语言可以直接同计算机内存打交道,这是C语言的低级语言特征。但是,由于指针变量的特殊性,使得C语言初学者在学习的时候往往感到很困惑,不知道何时取的是地址,何时取的是值。下面以一维数组和二维数组与指针变量的示例来理解指针变量的用法。

一、指针和一维数组

先来看指针和一维数组的关系,程序主要代码如下:

1:int arr[5]={1,2,3,4,5};

2:int *p;

3:p=arr;

4:printf(“%x %x %x ”,p,arr,&arr[0]);

5:printf(“%d %d %d %d ”,*p,*arr,arr[0],p[0]);

以上程序定义了一维整型数组arr和指向此一维数组的整型指针变量p。在定义时,符号*表示定义的是一个指针变量,符号[ ]表示定义的是一个数组。除了定义外,符号*和[ ]均具有“解地址”的功能,和另一个取地址符号“&”具有相反的功能,就像除法是乘法的逆运算一样。程序第4行运行后均输出十六进制的地址,p是指针变量,由于程序第3行的赋值语句,p和arr均表示地址,但p是地址变量,值可变,arr为地址常量,值不能变,即p++,++p,p- -,- -p均是可行的,但arr自增自减不行。由于p赋值为arr数组名,即p此时表示arr数组首地址,也是arr数组第0个元素的地址,所以p,arr,&arr[0]地址相同。程序第5行运行后均输出的是arr数组第0个元素的值。由第4行全为地址如何变成第5行的全为值呢?有两种方式,一种用“解地址”符号*,例如*p,*arr;另一种用“解地址”符号[ ],例如p[0],arr[0]。类似地,要表示arr数组第1个元素的地址,可以表示为p+1,arr+1,&arr[1]。要表示arr数组第1个元素的值,可以表示为*(p+1),*(arr+1),arr[1],p[1]。此时,p和arr可以互换。那&p表示什么呢?指针变量是一种特殊的变量,变量中存的是其它变量的地址值,但是指针变量本身也是要占内存空间的,所以&p表示的是指针变量p本身的地址,一般占4个字节或8个字节,这取决于编译器,例如VC++6.0给指针变量分配4个字节的空间,而DevC++给指针变量分配8个字节的空间。

二、指针和二维数组

接下来看指针和二维数组的关系,程序主要代码如下:

1:int a[3][4]={1,2,3,4,10,20,30,40,100,200,300,400};

2:int(*p)[4];

3:p=a;

4:printf("%x %x %x %d %x %x %d %d ",a,*a,*a+1,**a,a+1,*(a+1),**(a+1),*(*(a+1)+2));

5:printf("%x %x %x %d %x %x %d %d ",p,*p,*p+1,**p,p+1,*(p+1),**(p+1),*(*(p+1)+2));

6:printf("%x %x %x ",a[2],&a[2],&a[2][0]);

7:printf("%x %x %x ",p[2],&p[2],&p[2][0]);

8:printf("%d %d %d ",a[2][1],*(a[2]+1),*(*(a+2)+1));

9:printf("%d %d %d ",p[2][1],*(p[2]+1),*(*(p+2)+1));

以上程序定义了一个3行4列的二维整型数组a和指向此二维数组的整型指针变量p,如第2行这样定义的指针变量相当于行指针,可以用来遍历二维数组a的行,它与指向一维数组的指针变量不同之处在于,若指针变量p指向一维数组,则p+1表示一维数组下一个元素的地址,若指针变量p指向二维数组,则p+1表示二维数组下一行的首地址。当然,若指针变量p不是第2行这么定义的,而是直接定义为int *p;p=a;这种情况下p+1表示下一个元素的地址。由第4行可以知道,a、*a输出的都是一样的地址值,但含义是不同的,a表示的是整个数组的首地址和第0行的首地址,但*a表示的是第0行第0列元素的地址。符号*具有“解地址”的功能,但由于是二维数组,解一次地址并不能取到某个元素的值,如果再解一次地址,例如**a就表示第0行第0列元素的值。由于是二维数组,a+1和p+1一样都表示数组第1行的首地址。*(a+1)解一次地址,表示第1行第0列元素的地址,如果再解一次地址,则**(a+1)表示第1行第0列元素的值。*(a+1)+2表示行指针先定位到第1行第0列,表示地址,列指针再移动2个元素的位置,即表示定位到第1行第2列,仍然为地址。如果再用一次*号,则表示对应的元素的值了。类似地,符号[ ]具有解地址的功能。例如第6行a[2]表示第2行第0个元素的地址(从0行开始),&a[2]表示对第2行取地址,即第2行首地址,&a[2][0]表示对a[2][0]这个元素取地址,3个地址都是一样的,但含义不同。

由第8行可知,定义了二维数组和相应的行指针,要想取到数组元素的值,要么需要2个解地址符号*,要么需要1个*和1个[ ],要么需要2个[ ]。那么只有1个*或[ ]表示取到某个元素的地址,而1个*或[ ]都没有,则表示某一行的首地址。而取地址符号“&”就像是“*”和“[ ]”相反效果的符号一样。另外,由程序可知,指针变量名和数组名在很多情形下可以互相替换,效果一样。

三、总结

C语言的精华在于指针,而指针又是比较难学的,初学者最不容易理解的就是它的地址与值的关系。本文通过两个指针变量使用示例,将指针变量与数组中元素的地址和值作了详细的阐释,相关概念能帮助初学者熟练使用指针变量进行数组元素遍历。

猜你喜欢
数组指针C语言
JAVA稀疏矩阵算法
垂悬指针检测与防御方法*
基于Visual Studio Code的C语言程序设计实践教学探索
JAVA玩转数学之二维数组排序
51单片机C语言入门方法
基于C语言的计算机软件编程
更高效用好 Excel的数组公式
为什么表的指针都按照顺时针方向转动
高职高专院校C语言程序设计教学改革探索
寻找勾股数组的历程