数组元素是指针类型的数组就称为指针数组。指针数组的每一个元素都是指针变量。定义形式:类型名 *数组名[数组长度],如:
int *p[10]
二级指针,是指向另一个指向目标值的指针,也就是指向指针的指针。这个概念也叫做“多级间址”,或“多级间接地址(multiple indirection)”。普通指针的值是含预期值变量的地址。二级指针中,第一个指针含第二个指针的地址,第二个指针再指向含预期值的变量。
间接寻址的级数不受限制,但极少需要二级以上的间址。实际上,过深的间址难以理解,容易引起概念错误。作为指向指针的指针变量,必须这样声明,即通过在变量名的前面放置两个星号(**)来实现。
//示例二级指针的用法
#include <stdio.h>
main()
{
int x, *p, **q;
x=10;
p=&x;
q=&p;
printf("**q = %d\n",**q); /*打印出x的值*/
printf("&p = %u\n",&p);
printf("p = %u\n",p);
printf("&x = %u\n",&x);
}
仔细观察以下执行结果,注意分辨x的内存地址,p中存储的内存地址(就是x的内存地址),以及p自身的内存地址(就是q保存的内存地址)之间的不同。
为了通过二级指针间接访问到目标值,必须使用双星号。如上所示。
int main(int argc, char *argv[])
{
int a[5]={1,3,5,7,9};
int *p[5],i;
int **pp=p; //指向指针的指针,即二级指针
//给指针数组p赋值,让指针数组的每个元素都指向数组a中元素的内存地址
for(i=0;i<5;i++)
p[i]=&a[i];
//p[i]是指向a中元素的内存地址,*为取值运算符,则对该地址存储的数值进行取值
for(i=0;i<5;i++)
printf("%d",*p[i]);
printf("\n");
//pp是二级指针,即指向指针的指针,也是指向存储的内存地址,**也是取值运算,效果同上
for(i=0;i<5;i++,pp++)
printf("%d",**pp);
printf("\n");
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[])
{
int a[2][5]={1,3,5,7,9,2,4,6,8,0};
int(*p)[5]; //(*p)[5]是一个指针,这个指针指向包含5个元素的数组
int i;
p=a; //让p指向数组的首地址,即第一行第一个元素的地址
for(i=0;i<5;i++)
printf("%d ",(*p)[i]); //因为(*p)[5]是一个指针,它指向的是数组,所以这种写法相当于直引用数组
printf("\n");
p++; //让指针指向二维数组的第2行
for(i=0;i<5;i++)
printf("%d ",(*p)[i]);
printf("\n");
return 0;
}
运行结果:
(1)int (*p)[5],表示p是一个指针,它指向含有5个元素的一维数组。p也只能指向一个包含5个元素的一维数组,p就是该一维数组的的首地址。*p两边的括号是不可少的,因为[]的优先级比*高。
(2)p=a,使得p指向二维数组a的第一行。而后通过(*p)[i]访问该行的每一个元素。
(3)p++,使p指向二维数组a的第二行。
注意:区别int (*p)[5]和int *p[5]。前者是一个指针,它指向一个含有5个元素的数组。后者是一个数组(其元素是指针),它的长度为5,数组中每一个元素指向一个整形变量。