
指针高阶目录二级指针指针数组数组指针二维数组传参函数指针*********************************************在正文之前我们先了解一个知识arr[0数组第一个元素的地址arr数组第一个元素的地址arr整个数组的地址我们先来验证一下#includestdio.hintmain(){intarr[10]{1,2,3,4,5,6,7,8,9,10};printf(%p\n,arr[0];printf(%p\n,arr[0]1);printf(%p\n,arr);printf(%p\n,arr1);printf(%p\n,arr);printf(%p\n,arr1);return0;}如果我们只通过打印第135个printf时我们无法验证因为arr默认为首元素的地址所以135的输出结果是相同的均为首元素的地址那么我们通过第六个printf的结果可以得知在原来的基础上加了数组元素个数*指针对应字节大小个字节。这个是由位操作系统和开发环境决定的那么我们始终可以得出6与24是不同的相当与对每个元素都进行了1我们知道数组元素的地址是连续的那么我们也可以通过解引用比如 我们用int *parr: 那么 *(p1arr通过降级为首元素地址那么就相当于p是一个指向arr[0]的指针变量p相当于arr[0]的地址此时对p1,就相当于从arr[0]跳到了arr[1]1.二级指针二级指针主要作用是储存一级指针的地址数据类型** 指针变量名#includestdio.hintmain(){inta10;int*p1a;int**p2p1;return0;}这里我们就定义了一个二级指针我们来对**p2进行拆解我们先可以只针对p1,p2在针对a,p1来连接a和p2的关系首先我们需要知道p2指向的是p1的地址那么此时对p2进行解引用那么我们就拿到了p1的内容也是a的地址我们也知道对p1进行解引用得到是a的内容。也就是 **p2*p1a。那么我们打印的**p2也就是a的地址。printf(%p\n%p,*p2,p1);printf(%p\n%p,(**p),a);printf(%d\n%d,**p2,*p1);2.指针数组指针数组存放指针的数组。定义int*arr[];#includestdio.hintmain(){inta10;intb20;intc30;int*arr[]{a,b,c};printf(%d\n,*(arr1));printf(%d\n,**(arr1));return0;}通过输出结果我们可以知道通过一次解引用我们可以访问到变量本身的地址arr相当于数组元素首元素的地址也就是arr[0]我们在这里做一个区分数组元素内容是变量的地址而不是数组元素的地址我们通过访问数组元素的地址拿到的是变量的地址所以第一个printf打印的结果是b的地址以十进制整数输出的形式第二个printf输出的才是变量b的内容。3.数组指针数组指针指向数组的指针。是指针定义————————数据类型*指针名[数组长度]int (*p) [4]#includestdio.hintmain(){intarr[]{1,2,3,4};int(*p)[4]arr;printf(%p\n,*p);printf(%d\n,(*p)[1]);return0;}我们来看一下这两个printf分别打印的是什么第一个我们知道p指向的是数组所有的地址解引用就是数组名称我们知道数组名称会退化为首元素的地址所以第一个打印的也就是首元素的地址。第二个由第一个我们知道*p指的是数组名称那么*p[1]arr[1]到这里我们就再熟悉不过了。4.二维数组传参#includestdio.hvoidtest(int(*p)[5],intr,intc){inti0;intj0;for(i0;ir;i){for(j0;jc;j){printf(%d,*(*(pi)j);}printf(\n);}}intmain(){intarr[3][5]{{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15};test(arr,3,5);return0;}我们来解释一下* ( *(pi)j)我们知道p是一个数组指针i表示行j表示列p指向的是一个长度为5的一维数组相当于二维数组的一行当把二维数组arr传进时相当于第一行。现在我们来进行逐一的拆解1.pi:pi表示跳过i行此时指向的是二维数组的第i行的所有地址2. 解引用pi*pi)表示解引用第i行数组此时拿到的是数组名称会退化第一个元素的指针。那么arr[0]j就表示该行所有元素的地址此时再进行一次解引用就拿到了元素的内容。5.函数指针根据前面的学习整形指针数组指针的时候我们的类比关系我们不难得出结论函数指针变量应该是来存放函数地址未来通过地址能够调用函数。#includestdio.hvoidtest(){printf(hehehe\n);}intmain(){printf(%p\n,test);\\testtestreturn0;}输出的结果是相同的因此函数也存在地址。函数指针变量的使用#includestdio.hintadd(intx,inty){returnxy;}intmain(){int(*pf3)(int,int)add;printf(%d,(pf3)(2,3));printf(%d,*(pf3)(2,3));return0;}c语言标准规定函数名或函数指针在大多数表达式中会自动转化为指向函数的指针。