指针
---恢复内容开始---
通过前面的学习,我们了解了什么是指针,怎样去定义指针变量,以及如何去运用指针来完成变量a与变量b的交换。接下来,我们来看看如何通过指针引用数组,再讲这个问题之前,我们先来回顾一下有关数组的知识。
数组是一组有序数据的集合,它分为一维数组,和二维数组。下面,我举几个例子,方便读者理解和接受这个概念。
#include <stdio.h> int main() { int i,a[10]; for (i=0,i<=9;i++) a[i]=i; for(i=9;i>=0;i--) printf (“%d”,a[i]); printf(“\n”); return0; }
其中,上面程序的a[10],就是定义了一个存放一个有十个整数元素的数组。可以看到用一个“int a[10]”就相当定于了10个简单的整型变量,显得便捷方便。
在一维数组的基础上,我们就容易去定义二维数组了,请看下面的例子:
#include <stdio.h> int main() {int i,j,row=0;colum=0,max; int a[3][4]={{1,2,3,4},{9,8,7,6},{ -10,10,-5,2}}; max =a[0][0]; for(i=0;i<=2;i++) for (j=0;j<=3;j++) if(a[i][j]>max) {max=a[i][j]; row=i; colum=j } printf (“max=%d\nrow=%d\ncolum=%d\n”,max,row,colum); return0; }
回归到我们今天的话题,所谓的数组元素的指针就是数组元素的地址。
在c语言中,数组名,不包括形参数组名,形参数组名是不占用物理内存的,它代表的就是数组首元素的地址,也就是说
int *p=&a[0]; 它等效于下面两行: int *p; p=a;
如果我们想引用这个数组中的某个值时,怎么办?这时就可以进行指针的加或减法运算了,
假如我们定义了一个一维数组,用一个指针变量指向数组中的某个元素,则p+1指向下一个元素,同理,p-1指向上一个元素,但这时指针变量p的值未必增加一个或减少一个单位,这就要看定义的指针变量的数据类型,如:int型,p的值增加4(在vc++中运行),char型,p的值加1。
我始终认为例子能给读者更加深刻的理解,比起那些定义和理论,例子能让他们更易于接受和掌握。
#include <stdio.h> int main() {int a[10]; int i; printf(“please enter 10 integer number :”); for (i=0;i<=10;i++) scanf(“%d”,&a[i]); for (i=0;i<10;i++) printf (“%d”,a[i]); printf (“%d\n”); return0; }
#include <stdio.h> int main() {int a[10]; int i; printf(“please enter 10 integer number :”); for (i=0;i<=10;i++) scanf(“%d”,&a[i]); for (i=0;i<10;i++) printf (“%d”,*(a+i)); printf (“%d\n”); return0; }
这两个程序的运行结果都是相同的,仔细观察,这两个程序还是有细微的不同的,第九行的(a+i)是a数组中序号为i的元素的地址,*(a+i)是该元素的值。第七行中&a[i]也是同样用法。
#include <stdio.h> int main() {int a[10]; int *p,i; printf(“please enter 10 integer number :”); for (i=0,p=a;i<=10;i++,p++) scanf(“%d”,p); for (p=a;p<a+10;p++) printf (“%d”,*p); printf (“%d\n”); return0; }
这个程序是上面程序的一个改进,如果读者上机去运行一下的话,会发现,程序三会快于程序一,二。这就是指针变量的作用。即使是程序一,二,也要将a[i]转化为*(a+i)处理的,即先计算元素地址。
如果不用p变化的方法而改用数组名变化的方法行不行?假如将上述的第8 9行改为
for(p=a;a<=(p+10;a++) printf(“%d”;*);
请读者思考下。
下面来聊聊通过指针引用多维数组,其中最具代表性的就是二维数字了。
举一个小例
int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};
从二维数组的角度看,a代表二维数组首元素的地址,a+1代表下一行首元素的地址,a+2……便以此类推。
那么,如果想得到第二行第二个元素,那该如何用地址法表示吗?这里提供两种方法,①a[1]+2,②*(a+1)+2
它们代表的值为取它们地址的*,即*(a[1]+2)或*(*(a+1)+2)。如:要a[i][j]的值,用地址法表示为*(a[i]+j),*(*(a+i)+j)。
不妨假设,a的地址为1998,变量a是整型变量,在vc++中,一个整型变量占据4个字节,那么a+1和*(a+1)都是2016。请读者思考一下这是为什么。
指针在字符串方面的应用也是非常广泛的。
首先,我们来看看一个例题。
定义一个字符数组,其中存放字符串“All people are beautiful!”,输出该字符串和第8个字符。
#include <stdio.h> int main() {char string[]=“All people are beautiful!”}; printf(“%s\n”,string); printf(“%c\n”,string[7]); return0: }
实际上,string[7]就是*(string+7),string+7是一个地址,指向字符“C”。
它的另一种表示方法:
include <stdio.h> int main() {char *string=“All people are beautiful!”}; printf(“%s\n”,string); return0: }
对字符指针变量string初始化,实际上是把字符串第1个元素的地址赋给指针变量string,使string指向字符串的第一个字符。