该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
在C语言中,指针和数组有着紧密的联系,其原因在于凡是由数组下标完成的操作皆可用指针来实现。在数组中我们已经知道,可以通过数组的下标唯一确定了某个数组元素在数组中的顺序和存储地址,这种访问方式也称为"下标方式"。例如:
int a[5] = {1, 2, 3, 4, 5}, x, y;
x=a[2]; /* 通过下标将数组a下标为2的第3个元素的值赋给x,x=3 */
y=a[4]; /* 通过下标将数组a下标为4的第5个元素的值赋给y,y=5 */
由于每个数组元素相当于一个变量,因此指针变量既然可以指向一般的变量,同样也可以指向数组中的元素,也就是可以用"指针方式"访问数组中的元素。
例10-6:分析程序的运行过程和结果。
#include
main ( )
{ int a[ ] = {1, 2, 3, 4, 5} ;
int x, y, *p; /* 指针变量p */
p = &a[0]; /* 指针p指向数组a的元素a[0],等价于p=a */
x = *(p+2); /* 取指针p+2所指的内容,等价于x=a[2] */
y = *(p+4); /* 取指针p+4所指的内容,等价于y=a[4] */
printf ("*p=%d, x=%d, y=%d\n", *p, x, y);
}
语句"p=&a[0]"表示将数组a中元素a[0]的地址赋给指针变量p,则p就是指向数组首元素a[0]的指针变量,"&a[0]"是取数组首元素的地址。
C语言中规定,数组第1个(下标为0)元素的地址就是数组的首地址,同时C中还规定,数组名代表的就是数组的首地址,所以,该语句等价于"p=a;"。注意,数组名代表的一个地址常量,是数组的首地址,它不同于指针变量。
对于指向数组首地址的指针p,p+i(或a+i)是数组元素a[i]的地址,*(p+i)(或*(a+i))就是a[i]的值,其关系如图10-5所示。
图10-5 指针操作与数组元素的关系
对数组元素的访问,下标方式和指针方式是等价的,但从C语言系统内部处理机制上讲,指针方式效率高。需要注意的是:指针方式不如下标方式直观。下标方式可以直截了当地看出要访问的是数组中的哪个元素;而对于指向数组的指针变量,进行运算以后,指针变量的值改变了,其当前指向的是哪一个数组元素不再是一目了然。
例10-7:分析程序。
main( )
{ int a[ ] = {1, 2, 3, 4, 5, 6};
int *p;
p = a; /* 指针p为数组的首地址 */
printf("%d", *p);
printf(" %d\n", *(++p)); /* 以下两个语句等价 */
printf("%d", *++p);
printf(" %d\n", *(p--)); /* *(p--)等价于*p-- */
p += 3;
printf("%d %d\n", *p, *(a+3));
}
运行结果:
1 2
3 3
5 4
此例中指向数组a与指针变量p的指向变化情况见图10-6。
注意,第2个printf语句中的"*(++p)",是先使指针p自增加1,再取指针p值作"*"运算,它的含义等价于第3个printf语句中的"*++p"。而"*(p--)"是先取指针p值作"*" 运算,再使指针p自减减1。
用指针方式实现对数组的访问是很方便的,可以使源程序更紧凑、更清晰。
10.3.2 指针基本运算
对于指针的运算有三种:指针与正整数的加减运算、两个指针的关系运算,以及两个指针的减法运算。
1. 指针与正整数的加减运算
当指针p指向数组中的元素时,n为一个正整数,则表达式:
p+n
表示:指针p所指向当前元素之后的第n个元素。而表达式:
p-n
表示:指针p所指向当前元素之前的第n个元素。
最常见的指针加减运算为p++的含义是:指针加1,指向数组中的下一个元素;p--的含义是:指针减1,指向数组中的前一个元素。
指针与整数进行加减运算后,它们的相对关系如图10-7所示。
由于指针p所指的具体对象不同,所以对指针与整数进行加减运算时,C语言会根据所指的不同对象计算出不同的放大因子,以保证正确操作实际的运算对象。对于字符型,放大因子为1;对于整型,放大因子为2;对于长整型,放大因子为4;对于双精度浮点型,放大因子为 8。不同数据类型的放大因子等于一个该数据类型的变量所占用的内存单元数。