任务描述
一个变量有一个地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。所谓数组的指针是指数组的起始地址,数组元素的指针是数组元素的地址。
知识学习
(1)指向一维数组的指针
1)定义与赋值
这种定义方式与指向变量的指针变量的定义相同。例如:
int A[5];
int *p;
指针变量p 可以指向任何整型变量,因此也可以指向数组A 的任一元素。例如:
p=&A[0];
表示p 指向数组的第一个元素A[0]。
C语言规定,数组名代表数组的首地址,也是第一个数组元素的地址。因此上面的赋值语句等价于:
p=A;
指向数组元素的指针也可以在定义时赋初值。
2)引用
如有以下的定义和赋值:
int a[5],*p;
p=&a[1];
即指针变量p 指向数组元素a[1],则可以通过指针运算符“*”来对数组元素进行引用。
例如:
*p=10;
表示对p 所指向的数组元素a[1]赋值,上式等价于a[1] =10;
C语言规定,如果p 指向一个数组元素,则p +1 表示指向数组该元素的下一个元素。假设p=&a[0],则p+1 表示数组元素a[1]的地址。
引入指针变量后,就可以用两种方法来访问数组元素了。第一种方法为下标法,即用a[i]形式访问数组元素,在前面介绍数组时都是采用这种方法;第二种方法为指针法,即采用*(p+i)形式,用间接访问的方法来访问数组元素。
例7.5 用下标法输出一维数组中的全部元素。
3)一维数组数组作函数参数
在函数调用时,是把实参数组的首地址传递给形参数组,这样形参数组中的元素值如发生变化就会使实参数组的元素值也同时变化。如果令一个指针变量指向数组的第一个元素,或者等于数组名,此时数组名和指针变量的含义相同,都表示数组的首地址。所以实参和形参使用数组名时可以用指针变量替换。
例7.6 将一维数组a 中的n 个整数按相反顺序存放。
在前面曾经介绍过用数组名作函数的实参和形参的问题。在学习指针变量之后就更容易理解这个问题了。数组名就是数组的首地址,实参向形参传送数组名实际上就是传送数组的地址,形参得到该地址后也指向同一数组。这就好像同一件物品有两个彼此不同的名称一样。
4)指向一维数组元素的指针变量作函数参数
虽然数组名与指向数组首地址的指针变量都可以作函数参数,但是由于指向数组元素的指针变量不仅可以指向数组首地址,也可以指向数组中任何一个元素,所以指向数组元素的指针变量作函数参数的作用范围远远大于数组名作函数参数。
例7.7 求5 个学生的C语言平均成绩。
(2)指向二维数组的指针
1)指向二维数组元素的指针变量
在C语言中指针即是地址,如果指针变量等于只带一维下标的二维数组名,它的定义、赋值、引用与指向一维数组元素的指针变量形式相同,例如
int a[3][4],*p;
p=a[0];(www.xing528.com)
此时p 指向一维数组a[0]的起始地址,即p、a[0]、&a[0][0]相同。对其进行加法操作时p+1 等同于a[0] +1,都指向数组元素a[0][1]。所以*(p+1)等于元素a[0][1]的值。
例7.8 已知二维数组multi[2][3],输出全部元素。
2)指向二维数组中一维数组的指针变量
C语言规定一种指针变量,如果该指针变量等于不带任何下标的二维数组名,指针变量指向作为二维数组元素的一个一维数组(即二维数组的一行),这样对指针变量进行加减操作则指针将在二维数组中的行上移动。这种指针变量的定义形式如下:
类型符(*指针变量名)[指向的一维数组元素的个数]
那么对于一个由2 行3 列组成的二维数组a[2][3],如果指针变量p 指向这个二维数组中包含3 个元素的第一行一维数组,则指针变量p 的定义和赋值形式如下:
此时p 指向二维数组a 的起始地址。对其进行加法操作时p+1 等同于a+1,指向包含3个元素的一维数组a[1]。所以*(p+1)等于一维数组名a[1],*(p+1) +1 等于a[1] +1,所以*(*(p+1) +1)等于a[1][1]。
指向数组的指针变量在使用时,要注意与元素是指针类型的指针数组的区别。例如:
int (*q)[3],*p[3];
q 是指向一个包含3 个整型元素的一维数组的指针变量,p 是一个由p[0]、p[1]、p[2]共3 个指向整型数据的指针组成的一维数组。
例7.9 用指向二维数组中一维数组的指针变量输出数组中的元素。
说明:
本例程序中,p 是一个指针数组,3 个元素分别指向二维数组a 的各行。然后用循环语句输出指定的数组元素。其中*a[i]表示i 行0 列元素值;*(*(a +i) +i)表示i 行i 列的元素值;*p[i]表示i 行0 列元素值;由于p 与a[0]相同,故p[i]表示0 行i 列的值;*(p+i)表示0 行i 列的值。读者可仔细领会元素值的各种不同的表示方法。应该注意指针数组和二维数组指针变量的区别。这两者虽然都可用来表示二维数组,但是其表示方法和意义是不同的。
(3)指针与字符串
在C语言中,字符串是通过一维字符数组来存储的。因此,可以使用指向字符数组的指针变量来实现字符串的操作。
例7.10 下列程序实现字符串复制功能。
使用字符串指针变量与字符数组的区别,用字符数组和字符指针变量都可实现字符串的存储和运算。但是两者是有区别的,在使用时应注意以下几个问题:
①字符串指针变量本身是一个变量,用于存放字符串的首地址,而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以‘\0’作为串的结束,字符数组是由于若干个数组元素组成的,它可用来存放整个字符串。
②对字符数组作初始化赋值,必须采用外部类型或静态类型,如:
char st[] ={"C Language"};
而对字符串指针变量则无此限制,如:char *ps="C Language";
③对字符串指针方式 char *ps="C Language";可以写为:
char *ps;
ps="C Language";
而对数组方式:char st[] ={"C Language"};不能写为:char st[20];
st={"C Language"};而只能对字符数组的各元素逐个赋值。
从以上几点可以看出字符串指针变量与字符数组在使用时的区别,同时也可看出使用指针变量更加方便。
任务总结
如有代码:int a[8]; int *p; p=&a[0];,根据本项目所学习的知识则有如下关系:
①a[i]的地址:&a[i] 等价p+i。
②a[i]的值:a[i] 等价于p[i]。
③a[i]的值:a[i]等价于*(p+i)。
一维数组作为函数的参数时,如果需要将主调函数中的一维数组中所有的数组传递到被调函数中,一般通过使用数组名(代表数组起始地址)或指向数组的指针变量来实现。具体操作如下:
在主调函数中使用一维数组名作为调用函数的实参,在被调用函数中用指针变量作为形参来接受实参。
实参数实为数组首元素的地址,被调用函数其实接受的是该数组首元素的地址,使得备调用函数利用的形参完成了对主调函数中的数组的间接访问。
二维数组与指针、字符串与指针同理。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。