二级(多级)指针:保存指针变量地址的指针变量。
#include <stdio.h>
int main(){
int data = 10;
int *p = &data;
printf("data的地址是:%p\n",&data);
printf("p的地址是:%p\n");
int *pp = &p;
printf("pp的地址是:%p\n",pp);
return 0;
}
结果:
data的地址是:000000000061FE14
p的地址是:00007FFB7A9DFA30
pp的地址是:000000000061FE08
数据存储的值和地址
data:10 | 000000000061FE14 |
p:000000000061FE14 | 00007FFB7A9DFA30 |
pp:00007FFB7A9DFA30 | 000000000061FE08 |
也就是说二级指针的值为一级指针的地址, 是一个地址变量,虽然一级指针也能够访问指针变量的地址,但是不能**取出值,而二级指针局可以,二级指针值的访问同样和普通指针一样访问:
printf("pp访问到data:%d\n",**pp);
访问的结果:
pp访问到data:10
应用场景:
如果ppos没有赋予地址,那么它就成了野指针,如果我们根据当下函数指向数组的首地址,那么就会使数组发生改变,而我们想要的是查询数据。
什么是野指针?也就是在定义指针变量之后没有对它进行初始化,指向非法的内存地址指针叫作野指针,会出现段错误,可以通过二级指针将其本身的地址传递过来,间接修改指针变量的指向,指向数组。
#include <stdio.h>
void getscore(int pos,int (*pstu)[4],int *ppos){
ppos = (int *)(pstu+pos);
}
int main(){
int scores[3][4]={{11,22,33,44},{55,66,77,88},{10,20,30,40}};
int pos;
printf("请输入要查询学生序号数:0,1,2\n");
scanf("%d",&pos);
int *ppos;
getscore(pos,scores,&ppos);
for(int i=0;i<4;i++){
printf("%d ",*ppos++);
}
return 0;
}
使用二级指针:
#include <stdio.h>
void getscore(int pos,int (*pstu)[4],int **ppos){
*ppos = (int *)(pstu+pos);
}
int main(){
int scores[3][4]={{11,22,33,44},{55,66,77,88},{10,20,30,40}};
int pos;
printf("请输入要查询学生序号数:0,1,2\n");
scanf("%d",&pos);
int *ppos;
getscore(pos,scores,&ppos);
for(int i=0;i<4;i++){
printf("%d ",*ppos++);
}
return 0;
}
二级指针指向二维数组:
假设有一个二维数组,数组含三个元素,每个元素包含四个数据,转换为指针时相当于int (*p)[3],只不过不关心数组有多少个元素,关系元素包含了多少子元素。
int scores[3][4]={{11,22,33,44},
{55,66,77,88},
{10,20,30,40}}; //等价于int (*p)[3]
而*scores是列地址,按理来说*p也是一个列地址,但是如果我们直接使用*p会发生段错误,因为*p是一个野指针,需要指向一个地址。
printf("*p = %p",*p);
printf("*scores = %p",*scores);
例如:
int (*p)[4] = *p;
int **p = &p;