二级指针探讨
在周朝的时候,有一个观念很有意思,就是 “我上级的上级 不是我的上级”,那时候,周王 要下达某个指令给全国百姓,只能通过 各个分封的诸王,然后 诸王再下达命令给自己的国民,如果某个诸王如果不听周王的话,那周王其实 也一点办法没有的。所以 ,周王想要指挥某个诸侯国的臣子,必须通过这个诸侯国的国君。
那么 回到二级指针的话题,程序员想要 操作某段内存,必须通过 一级指针,这是必然的,但是如果现在我像周王一样了 ,无法直接下达命令给一级指针(臣子),只能通过 国君即二级指针来操作,因为我也并不知道这个臣子被这个小国君藏哪里了。
因此 可以这样理解:
周王要找某个臣子 做事的过程是:
- *国君 ---> 臣子的 位置
- *臣子的位置 --->吩咐之
直接的两次 解引用国君就可以直接指挥臣子了
- **国君 --->指挥臣子
当然,如果 你连国君都不知道 在哪里,你就得问 你身边的 太监了,那就是 三级指针的事儿了。
这种联想式层级式的 索引,在C语言中,就是 多级指针。
这个例子 故意不总用地址的概念,而是用了指挥、操纵相关的词,是希望我们不要总把指针和地址关联,解引用指针的目标是为了操作它所指代的内存区域。
比如,这个周王 总算找到了这个臣子,干什么呢,其实 ,是为了让他来自己身边做太监。
好了,二级指针的概念 算是 明白了,那怎么用呢?
还是 把 那个想做太监的臣子叫来,他会这样上达天听:先将自己的 驻地告诉 自己的国君,然后这个国君再把自己的分封之地告诉周王,(当然,为什么不直接告诉周王这个臣子的具体位置呢,因为 国君 觉得自己的臣子要自己管理,不能越过他这个二级指针。这个 和天朝的某些制度还是很像的)。
在这个例子里,我们可以知道,解引用和 取地址 是两个相反的 过程。
解引用时,我们是 周王
取地址时,我们是 臣子
二者关联,相辅相成,臣子做成太监这事才能 成真。
感觉自己写了很多废话....
理解了概念,我们 开始来 改造 大臣:
#include<stdio.h>
int main(void)
{
char*position1 ="Courtier"; //身份象征,大臣
char*position2 ="Eunuch"; //身份象征 ,太监
char*person =position1; //目前是大臣
printf("I am %s now,I am not happy!\n",person);//目前是大臣,他不开心
char**king =(char**)(&person); //大臣将自己的住址告诉国君
char**emperor = king ; //国君将自己的封地告诉 周王
*emperor = position2 ; //周王实现对大臣的 太监改造
printf("I am %s now!,waw ,I am happy!\n",person); //很高兴的太监来了
}
输出如下:
I am Courtier now,I am not happy!
I am Eunuch now!,waw ,I am happy!
有人 说,干嘛要这么麻烦,自己直接切了不就行了么?额,自己把自己切了也是可以的:毕竟从代码上看,直接person = position2,就行了。
但是从故事上看,这样做 没有得到皇家 周王的认可,所以行不通,因为野生太监不好当啊。
从代码上看,使用场景也少了,因为 二级指针 多作为函数的参数 存在着,直接在main中玩二级指针,我还只在 我这个例子中用过。
毕竟,由周王亲自动手净身的太监 还是极少的,大部分都是净身房函数做的嘛。
那么 作为 函数场景,我们 该怎么做呢:
int makeEunuch(char** person,char* position)
{
*person = position;
return0;
}
int main(void)
{
char*position1 ="Courtier";
char*position2 ="Eunuch";
char*person = position1;
printf("I am %s now,I am not happy!\n",person);
char**king =(char**)(&person);
char**emperor = king ;
MakeEunuch(emperor,position2);
printf("I am %s now!,waw ,I am happy!\n",person);
}
输出与上面是一样的,
将 太监改造工程函数化了,这在实际代码中是 非常常见的。
那么 在改造函数中 ,直接改,可以么?看以下代码:
int mayMakeEunuch(char* person,char* position)
{
person = position;
return0;
}
int main(void)
{
char*position1 ="Courtier";
char*position2 ="Eunuch";
char*person = position1;
printf("I am %s now,I am not happy!\n",person);
char**king =(char**)(&person);
char**emperor = king ;
mayMakeEunuch(person,position2);
printf("I am %s now!,waw ,I am happy!\n",person);
}
输出的结果是:
I am Courtier now,I am not happy!
I am Courtier now!,waw ,I am happy!
看来,即便是明显对这个person进行太监改造,他最后还是个大臣,其实 这才符合常理啊,知道周王 要拉他去做 太监,于是 ,在执行太监改造的时候,他拉了 个人冒名顶替他,玩起金蝉脱壳了,当然很高兴啊。而净身房确实将那个顶替的人 变成了太监,但是在 回到周王那里时,这个该死的 太监就死了,这与我们作为周王的愿景是相悖的,因为 ,我没有得到我要的太监啊!记住金蝉脱壳这个成语,这是 函数 传参的 全部事实。
可以另见 :从一段经典错误代码说起——关于局部变量指针和函数传参的问题分析
当然,这里 我也仅仅是通过这个例子 ,告诉大家二级指针的使用场景,至于说什么地址的地址啊,这个 我也知道啊,但是我没有写在这里,毕竟实在太抽象,有的人 连地址都抽象不出来。而地址这个概念其实 是 微机时代就有的产物,不知道计算机原理的人 实在难以消化,而现在,我选择要么做周王,要么做太监。