二级指针
C语言允许有多级指针存在,在实际的程序中一级指针最常用,其次是二级指针。
二级指针就是指向一个一级指针变量地址的指针。
三级指针基本用不着。
二级指针
二级指针就是指向指针的指针,指向地址的地址,有点套娃...直接看下面的案例更好理解吧。
* p 、* * p、p[0]、p[0][0]
#include<stdio.h>
int main(void)
{
int a[] = { 1,2,3 };
int b[] = { 4,5,6 };
int c[] = { 7,8,9 };
//指针数组是一个特殊的二维数组模型
//指针数组对应于二级指针
int* arr[] = { a,b,c }; //这里不用取地址符号&,因为数组名就是数组的首地址
//指针数组和二级指针建立关系
int** p = arr;
printf("%p\n", a); //输出:0xFF0000
printf("%p\n", b); //输出:0xFF0032
printf("%p\n", c); //输出:0xFF0064
printf("%p\n", arr); //输出:0xFF0086
printf("%p\n", *p); //输出:0xFF0000
printf("%d\n", **p); //输出:1
printf("%p\n", p[0]); //输出:0xFF0000
printf("%d\n", p[0][0]); //输出:1
return 0;
}
**(p+1)、 * (*p+1)
#include<stdio.h>
int main(void)
{
int a[] = { 1,2,3 };
int b[] = { 4,5,6 };
int c[] = { 7,8,9 };
//指针数组是一个特殊的二维数组模型
//指针数组对应于二级指针
int* arr[] = { a,b,c }; //这里不用取地址符号&,因为数组名就是数组的首地址
//指针数组和二级指针建立关系
int** p = arr;
printf("%d\n",**(p+1)); //输出4
return 0;
}
#include<stdio.h>
int main(void)
{
int a[] = { 1,2,3 };
int b[] = { 4,5,6 };
int c[] = { 7,8,9 };
//指针数组是一个特殊的二维数组模型
//指针数组对应于二级指针
int* arr[] = { a,b,c }; //这里不用取地址符号&,因为数组名就是数组的首地址
//指针数组和二级指针建立关系
int** p = arr;
printf("%d\n",*(*p+1)); //输出:2
return 0;
}
* (*(p+1))+1)
#include<stdio.h>
int main(void)
{
int a[] = { 1,2,3 };
int b[] = { 4,5,6 };
int c[] = { 7,8,9 };
//指针数组是一个特殊的二维数组模型
//指针数组对应于二级指针
int* arr[] = { a,b,c }; //这里不用取地址符号&,因为数组名就是数组的首地址
//指针数组和二级指针建立关系
int** p = arr;
printf("%d\n",*(*(p+1))+1); //输出:5
return 0;
}
p[i][j]、* (p[i]+j))、* (*(p+i)+j))
#include<stdio.h>
int main(void)
{
int a[] = { 1,2,3 };
int b[] = { 4,5,6 };
int c[] = { 7,8,9 };
//指针数组是一个特殊的二维数组模型
//指针数组对应于二级指针
int* arr[] = { a,b,c }; //这里不用取地址符号&,因为数组名就是数组的首地址
//指针数组和二级指针建立关系
int** p = arr;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
//printf("%d ",p[i][j]);
//printf("%d ",*(p[i]+j));
printf("%d ",*(*(p+i)+j));
}
puts(""); //相当于输出一个换行\n
}
return 0;
}
输出:
1 2 3
4 5 6
7 8 9
上面三个输出的结果一样!
变量的二级指针
#include<stdio.h>
int main(void)
{
int a = 10;
int b = 20;
int* p = &a;
int** pp = &p;
printf("%p\n",&a); //输出:0095FA7C
printf("%p\n",&b); //输出:0095FA70
printf("%p\n",p); //输出:0095FA7C 这里存的是a的地址
printf("%d\n",*p); //输出:10 这里取的是a的值
printf("%p\n",&p); //输出:0095FA64
printf("%p\n",pp); //输出:0095FA64 这里是二级指针pp存储的地址(值)
printf("%p\n",&pp); //输出:0095FA58 这里是二级指针pp自己的地址
*pp = &b; //等价于 p = &b; 把 指针的指针 pp 指向 b 的地址
printf("%d\n", *p); //输出:20 因为前一步指向b的地址了,所以取出的也是b的值20
//*pp = 100; 野指针,合理修改的是地址,而不是值
**pp = 100;
// *pp 取的是 一级指针 的值(地址)0095FA70 ,这是变量b的地址,因为之前 *pp = &b; 操作了,
//**pp 相当于 *(0095FA70) 取得是变量b的值20;截止把数值100赋值给那个地址,也就是值覆盖,变成了100
printf("%d\n", *p); //输出:100
printf("%d\n", a); //输出:10
printf("%d\n", b); //输出:100
//printf("%p\n",a);
return 0;
}
参考:
[1]C基础讲义2018修订版(黑马程序员)