每天下课之后,都感觉老师上课在神仙编程,我们一群凡人在底下面无表情地走神,前一秒还是在讲加减乘除的基本用法,后一秒就变成了指针数组、数组指针、结构体指针和N级指针的性质以及运用............(真是令人头秃 —^—)
————————————————下面是正文——————————————————
一.N级指针
(1). 一级指针
一级指针是我们最经常使用的指针,它的定义简单明了——> 类型* 变量名 ,具体一级指针的定义我在前面的博客里已经对其有了介绍,感兴趣的童鞋可以点击: https://blog.csdn.net/qq_41884002/article/details/84258830 查看~~ 下面是对一级指针进行一点知识扩展,请看下面代码
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
printf("%d\n",*p1);
return 0;
}
编译结果毫无新意
然后再看下汇编
结果就是毫无新意的取出p1所存的地址中的值而已~那么如果我把代码修改成这样,结果还会一样吗?
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
printf("%d\n",*(p1+0));
return 0;
}
汇编如下
嗯......在汇编的角度来看和直接写*p1是完全一样的,那编译结果不出意料的话应该也是一样的
如果这样的话,按照我对汇编的理解,突然想到了这样的一种修改方法
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
printf("%d\n",p1[0]);
return 0;
}
查看一下结果
答案是出其地一致的,但是汇编会不会是不一致的呢???
答案是:它们三个汇编是一样的。这个时候,我们可不可以得出这样一个结论呢?
*(P+ i)= P [ i ]
我们尝试一下代码
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
printf("%d\n",*(p1+1));
printf("%d\n",p1[1]);
printf("\n");
printf("%d\n",*(p1+2));
printf("%d\n",p1[2]);
return 0;
}
结果如下:
得到的结果也是完全一致的,所以,我们可以得出第一个结论:在一级指针中,*(P+ i)= P [ i ]
(2). 二级指针
加一颗 ” * “ 就能成为一级指针,那么两颗 ” * “ 就是传说中的二级指针了。二级指针其实就是我们俗称的 “ 指针的指针” ,很多书上或者网上都故作玄虚地摆弄着术语说
嗯......感觉这些人写这些东西就是想混肴我的思路,故意不让我听明白的样子......其实二级指针可以这样理解!
int x = 100;
int* p1 = &x;
p1是个变量名,它的类型为int* ,它里面保存的是 x 的地址。over。
int x = 100;
int* p1 = &x;
int** p2 = &p1;
p2是个变量名,它的类型为int**,它里面保存的是 p1 的地址。over。
那我可不可以这样写呢?
int** p2 = &x;
编译器告诉我们是不能的。
错误的原因是不能把一个类型为 int* 的值赋值给 int** ,也就是我在文章开头给出的那个连接的博客里面提到过的 ”&x“ 是 int* 类型的,只能用同是 int* 类型的p1来接收,而”&p1“ 是int** 类型的,只能用类型是int**的p2来接收。
综上所述,二级指针(指针的指针),就是用来保存类型为两颗” * “ 的值的容器。over。
接下来,我要放大招了!
根据一级指针中得出的一个结论:*(P+ i)= P [ i ] ,那在二级指针里面,我们可不可以大胆地这样来定义?
在二级指针中,*(*(P+ i)+j ) = P [ i ] [ j ]
我们写出这样的代码
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
int** p2 = &p1;
printf("%d\n",*(*p2));
printf("%d\n",*(*(p2+0)+0));
printf("%d\n",p2[0][0]);
return 0;
}
编译的结果如下
再看一眼汇编
也是完全一样的,所以可以得出这样的结论:在二级指针中,*(*(P+ i)+j ) = P [ i ] [ j ]
——————————————————小插曲————————————————————
有些同学不是很懂 *(*p2) 得出来的为什么会是 100,这样简单地说一下:首先 (*p2 )得到的值是 p2所保存的地址(就是p1 的地址) 所指向的东西 (就是 x 的地址),所以 (*P2) == x 的地址,然后 *(*p2) 得到的值是(*p2)所保存的地址(就是x 的地址) 所指向的东西 (就是 100),所以 *(*P2) == 100
—————————————————————————————————————————
(3). 三级指针
换句话说,三级指针就是” 指针的指针的指针 “,不过经过上两级的指针的 ”洗礼“,估计再怎么复杂的指针,都不会再搞混定义了,所以在此不再累赘。三级指针的赋值也是和二级指针一样,赋值号左右的类型需要同时相等才能赋值,所以
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
int** p2 = &p1;
int*** p3 = &p2;
return 0;
}
然后我们再来把上两级的套路套在三级指针上面
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
int** p2 = &p1;
int*** p3 = &p2;
printf("%d\n",*(*(*p3)));
printf("%d\n",*(*(*(p3+0)+0)+0));
printf("%d\n",p3[0][0][0]);
return 0;
}
发现编译的结果
和汇编的过程
也是完全一样的,所以,当我们在往下一直探索 N级指针时,我们可以总结出几个这样的结论:
1. *()与 【 】 是可以互相转换的
2. *(P+I) = P [ I ]
*(* (P+I) + J ) = P[ I ] [ J ]
............