一、二级指针
地址就是指针,一级指针就是保存一个变量或常量的地址,二级指针就是保存一级指针变量(中间媒婆)的地址,间接访问一级指针指向的变量或常量。(以此类推,还有三级,四级...指针)
原理图:
代码验证:
二级指针与const结合
const int *p=&a <=>int const * p=&a ->表明不能通过该指针间接变量a的值。
int * const p=&a ->表明该指针变量(p)只能指向变量a的地址。
const int **pp=&p <=>int const ** pp ->表明不能通过该指针间接变量a的值。
int * const * pp=&p; ->表明不能通过*pp指针修改*pp所指向的对象(即一级指针p指向的对象)。
int ** const pp=&a ->表明该指针变量(pp)只能指向一级指针(p)的地址。
综上得出:用const修饰后的部分可以看作常量,也就以为着不能对它进行操作,未被修饰的部分则可以进行操作。
1.指向常变量的指针。
eg: const int a=10;//表明这是一个值不可以被改变的常变量
因此 我们在定义一级指针时:const int* p=&a;
定义二级指针时:const int ** pp=&a;
2.根据需求对指针进行const 修饰,可以是多个const
我们常常将const 用在自定义的函数形参中,确保数据不会被修改。
二、二维数组参数传递的不同形式
不理解可以看我之前的文章:
二维数组a的数组名a,a[0],&a,&a[0]的联系,和指针的关系_槐夏风清7的博客-CSDN博客
一维数组a,数组名a和首元素地址&a[0]和&a地址相同,他们到底有何不同_槐夏风清7的博客-CSDN博客
1.通过数组指针作形参
#include <stdio.h>
//数组指针
void print(int(*c)[2])
{
printf("%d\n", **c); //c[0][0]
printf("%d\n", *(*(c + 1) + 1));//c[1][1]
printf("%d\n", c[0][1]); //c[0][1]
printf("%d\n", (*c)[1]); //c[0][1]
printf("%d\n", *c[1]); //c[1][0]
}
int main()
{
int a[2][2] = { {1,2},{5,3} };
print(a);
}
2.通过二维数组指针作形参
#include <stdio.h>
//二维数组指针(&a)
void print(int(*c)[2][2])
{
printf("%d\n", ***c); //c[0][0]
printf("%d\n", *(*(*c + 1) + 1));//c[1][1]
printf("%d\n", c[0][1][1]); //c[1][1]
printf("%d\n", (*c)[0][1]); //c[0][1]
printf("%d\n", (**c)[1]); //c[0][1]
printf("%d\n", *c[0][1]); //c[1][0]
printf("%d\n", *(*c)[1]); //c[1][0]
}
int main()
{
int a[2][2] = { {1,2},{5,3} };
print(&a);
}