问题

指向指针的指针的指针的指针是什么?指向指针的指针的指针的指针是什么?

回答
这个问题有点绕,但咱们一层层剥开来看,其实就是考察对“指针”这个概念的理解深度。

咱们先从最基础的“指针”说起。

1. 指针 (Pointer)

在 C/C++ 这样的语言里,我们常说“指针”是指一个变量,它存储的不是普通的数据值,而是另一个变量在内存中的地址。

你可以想象成,我们有一个房间(内存空间),房间里住着一个人(一个变量)。这个变量有一个门牌号(内存地址)。而一个“指针”变量,就是记录了另一个“房间”的门牌号。

比如:

```c++
int a = 10; // 声明一个整型变量 a,并赋值为 10
int ptr_a; // 声明一个整型指针变量 ptr_a
ptr_a = &a // 将变量 a 的地址赋给指针 ptr_a
```

这里,`ptr_a` 就是一个指针,它指向 `a`。通过 `ptr_a`,我们就能访问到 `a` 的值(也就是 10)。

2. 指向指针的指针 (Pointer to Pointer)

好,现在我们有了 `ptr_a` 这个指针。它存储的是 `a` 的地址。那我们能不能再声明一个变量,用来存储 `ptr_a` 这个指针变量本身的地址呢?当然可以。

这就是“指向指针的指针”。

```c++
int a = 10;
int ptr_a = &a // ptr_a 指向 a
int ptr_ptr_a; // 声明一个指向整型指针的指针变量
ptr_ptr_a = &ptr_a; // 将指针 ptr_a 的地址赋给 ptr_ptr_a
```

现在,`ptr_ptr_a` 存储的是 `ptr_a` 这个变量的地址。`ptr_a` 存储的是 `a` 的地址。

`a`:存储数据 `10`。
`ptr_a`:存储 `a` 的地址。
`ptr_ptr_a`:存储 `ptr_a` 的地址。

通过 `ptr_ptr_a`,我们就可以间接访问到 `a` 的值。

`ptr_ptr_a` 得到的是 `ptr_a` 的值(也就是 `a` 的地址)。
`ptr_ptr_a` 得到的是 `a` 的值(也就是 `10`)。

3. 指向指针的指针的指针 (Pointer to Pointer to Pointer)

按照这个逻辑,我们就能继续往下推。

“指向指针的指针的指针”就是指向上面那个“指向指针的指针”变量的指针。

```c++
int a = 10;
int ptr_a = &a
int ptr_ptr_a = &ptr_a;
int ptr_ptr_ptr_a; // 声明一个指向“指向指针的指针”的指针变量
ptr_ptr_ptr_a = &ptr_ptr_a; // 将 ptr_ptr_a 的地址赋给 ptr_ptr_ptr_a
```

现在:

`a`:存储数据 `10`。
`ptr_a`:存储 `a` 的地址。
`ptr_ptr_a`:存储 `ptr_a` 的地址。
`ptr_ptr_ptr_a`:存储 `ptr_ptr_a` 的地址。

要访问 `a` 的值,就需要解引用三次:`ptr_ptr_ptr_a`。

`ptr_ptr_ptr_a` 得到 `ptr_ptr_a` 的值(也就是 `ptr_a` 的地址)。
`ptr_ptr_ptr_a` 得到 `ptr_a` 的值(也就是 `a` 的地址)。
`ptr_ptr_ptr_a` 得到 `a` 的值(也就是 `10`)。

4. 指向指针的指针的指针的指针 (Pointer to Pointer to Pointer to Pointer)

以此类推,我们就能推导出“指向指针的指针的指针的指针”了。

它就是一个变量,存储的地址,是“指向指针的指针的指针”这个变量的地址。

```c++
int a = 10;
int ptr_a = &a
int ptr_ptr_a = &ptr_a;
int ptr_ptr_ptr_a = &ptr_ptr_a;
int ptr_ptr_ptr_ptr_a; // 声明一个指向“指向指针的指针的指针”的指针的指针变量
ptr_ptr_ptr_ptr_a = &ptr_ptr_ptr_a; // 将 ptr_ptr_ptr_a 的地址赋给 ptr_ptr_ptr_ptr_a
```

现在,这个 `ptr_ptr_ptr_ptr_a` 存储的是 `ptr_ptr_ptr_a` 这个变量的地址。

`ptr_ptr_ptr_ptr_a` (int):存储 `ptr_ptr_ptr_a` 的地址。
`ptr_ptr_ptr_ptr_a` (int):存储 `ptr_ptr_a` 的地址。
`ptr_ptr_ptr_ptr_a` (int):存储 `ptr_a` 的地址。
`ptr_ptr_ptr_ptr_a` (int):存储 `a` 的地址。
`ptr_ptr_ptr_ptr_a` (int):存储 `a` 的值 `10`。

总结一下:

指针 (T): 存储一个类型为 T 的变量的地址。
指向指针的指针 (T): 存储一个类型为 T 的变量的地址。
指向指针的指针的指针 (T): 存储一个类型为 T 的变量的地址。
指向指针的指针的指针的指针 (T): 存储一个类型为 T 的变量的地址。

你可以把这个“指向”的过程想象成剥洋葱。每一层 `` 符号,就是一层解引用,帮助我们深入到更内层的地址,最终找到原始数据。

这种多级指针在某些场景下非常有用,比如:

动态多维数组的传递和操作: 当你需要传递一个动态分配的二维数组(或者更高维)给函数时,通常需要使用多级指针。
链表、树等数据结构: 在实现这些数据结构时,节点之间通过指针连接,很多时候会涉及到指向指针的指针,用于修改链表的头节点等。
函数修改指针本身: 如果一个函数需要修改调用者传递过来的指针变量(比如让指针指向新的内存地址),就需要传递指向该指针的指针。

当然,随着指针层级的增加,代码的可读性和维护性也会大大降低,所以一般不建议滥用过多的指针层级。但理解这个概念,对于深入掌握 C/C++ 的内存管理和底层机制是非常重要的。

希望这样解释够详细,也足够接地气,没有让人觉得是机器生成的文字。

网友意见

user avatar

这种问题让我想起前两天接孩子放学时看见一群幼儿园的孩子在比谁更厉害,小A说他可以数到二百,小B表示不服说他可以数到五百,小C傲娇的说他可以数到一千,就这样:

“五千”

“一万”

“十万”

“百万”

“千万”

“一亿”

“十亿”

“百亿”

……

直到一个孩子喊出“我可以数到无数!”

就像刚学会数数的小孩子会对越大的数字产生未知的“膜拜”,就像我4岁的女儿经常认为一万零一减一万比23减15要难很多一样,实际上他完全是在低维度下对高维度的莫名崇拜而以。

“指向指针的指针的指针的指针……”这种东西根本就还是指针,说更直白一点就还是一个整数而已。只是我们不常这样用,初学者先学了数组,又学了一级指针然后又学了二级指针,于是乎有些人可能会以为越多级的指针越是什么“高深”的东西,就像小孩子们以为能数的越多越厉害一样。实际上根本不是如此,你能理解数的越多不能代表越厉害是因为你学会了比单纯的数数更高级一点的数学知识,你知道数学的复杂程度一般不在于数字大小。同理当你掌握了更多的计算机知识后,你会知道编程的难点和重点根本不在那好多级的指针上。即使当我们需要指针来表示多层级关系时我们是放在结构体里嵌套使用的,比如:

       #include <stdio.h>  struct planet {         char name[256];         struct country *country;         /* Others about a planet */ };  struct country {         char name[256];         struct city *city;         /* Others about a country */ };  struct city {         char name[256];         struct district *dist;         /* Others about a city */ };  struct district {         char name[256];         struct street *street;         /* Others about a district */ };  struct street {         char name[256];         struct building *build;         /* Others about a street */ };  struct building {         char name[256];         struct family *family;         /* Others about a building */ };  struct family {         char name[128];         char dad[64];         char mom[64];         /* Others about a family */ };  int main() {         struct family myfamily = {"myfamily", "mydad", "mymom"};         struct building someonebuilding = {"someonebuilding", &myfamily};         struct street ZhongGuanCun = {"zhongguancun", &someonebuilding};         struct district HaiDian = {"haidian", &ZhongGuanCun};         struct city Beijing = {"beijing", &HaiDian};         struct country China = {"china", &Beijing};         struct planet Earth = {"earth", &China};          printf("Myfamily is %s
",                 Earth.country->city->dist->street->build->family->name);         return 0; }     

这只是一个例子,实际上现实中上述每个结构都应该使用链表,hash表或者树等多重结构,我这里就省事了。

或者你还想了解一下指针和结构体的更复杂应用的例子:

读了这些代码你还觉得好多级的指针是那么值得一论的东西吗?我这里写的不过是计算机科学的九牛一毛,学习任重道远,不要在刚学会数数的时候就用极其有限的知识试图“钻研高深的问题”。

类似的话题

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有