为什么指针是许多刚开始学习C或c++,甚至上了大学的学生困惑的主要因素?有没有什么工具或思维过程可以帮助你理解指针在变量、函数和级别之外是如何工作的?

有什么好的实践可以让人达到“啊哈,我懂了”的水平,而不会让他们陷入整体概念中?基本上,就是模拟场景。


当前回答

我想我应该在这个列表中添加一个类比,当我作为计算机科学导师解释指针时(回到过去),我发现它非常有用;首先,让我们:


做好准备:

考虑一个有3个车位的停车场,这些车位是编号的:

-------------------
|     |     |     |
|  1  |  2  |  3  |
|     |     |     |

在某种程度上,这就像内存位置,它们是连续的和连续的。有点像数组。现在它们中没有汽车,所以它就像一个空数组(parking_lot[3] ={0})。


添加数据

停车场永远不会空着太久……如果有,那就没有意义了,也没有人会去建造。假设随着时间推移,停车场里停满了3辆车,一辆蓝色的,一辆红色的,一辆绿色的

   1     2     3
-------------------
| o=o | o=o | o=o |
| |B| | |R| | |G| |
| o-o | o-o | o-o |

这些车都是同一类型(car),所以一种思考方法是,我们的车是某种数据(比如int),但它们有不同的值(蓝色,红色,绿色;这可以是一个颜色枚举)


进入指针

现在如果我带你到这个停车场,让你给我找一辆蓝色的车,你伸出一根手指,指着点1的一辆蓝色的车。这就像获取一个指针并将其分配给一个内存地址(int *finger = parking_lot)

你的手指(指针)不是我问题的答案。看你的手指什么也不能告诉我,但如果我看你手指指向的地方(取消指针指向),我就能找到我要找的车(数据)。


重新分配指针

现在我可以让你找到一辆红色的车,你可以把你的手指转向一辆新车。现在您的指针(与之前的指针相同)正在向我显示相同类型(汽车)的新数据(可以找到红色汽车的停车位)。

指针在物理上没有变化,它仍然是你的手指,只是它显示给我的数据变了。(“车位”地址)


双指针(或指向指针的指针)

这也适用于多个指针。我可以问指向红色汽车的指针在哪里,你可以用另一只手用一根手指指向第一个手指。(这就像int **finger_two = &finger)

现在如果我想知道蓝色的车在哪里,我可以顺着食指的方向到第二根手指,到那辆车(数据)。


悬空指针

现在让我们假设你感觉自己很像一座雕像,你想一直用手指着那辆红色的车。如果那辆红色汽车开走了怎么办?

   1     2     3
-------------------
| o=o |     | o=o |
| |B| |     | |G| |
| o-o |     | o-o |

你的指针仍然指向红色汽车的位置,但它已经不在了。假设一辆新车停在那里……一辆橙色的汽车。现在如果我再问你,“红色的车在哪里”,你仍然指着那里,但现在你错了。那不是红色的车,那是橙色的。


指针的算术

好的,你仍然指着第二个停车位(现在被橙色车占据了)

   1     2     3
-------------------
| o=o | o=o | o=o |
| |B| | |O| | |G| |
| o-o | o-o | o-o |

我现在有个新问题…我想知道下一个停车位的车是什么颜色。你可以看到你指向点2,所以你只要加1,你就指向下一个点。(手指+1),现在因为我想知道那里的数据是什么,你必须检查那个点(不仅仅是手指),所以你可以遵从指针(*(手指+1)),以看到那里有一辆绿色的汽车(该位置的数据)

其他回答

我认为理解指针的主要障碍是糟糕的老师。

几乎每个人都被教导过关于指针的谎言:它们只不过是内存地址,或者它们允许你指向任意位置。

当然,他们很难理解,危险,半魔法。

这些都不是真的。指针实际上是相当简单的概念,只要你坚持c++语言对它们的描述,不要给它们灌输“通常”在实践中会起作用的属性,但语言却不能保证,因此不是指针实际概念的一部分。

几个月前,我试图在这篇博客文章中对此进行解释——希望它能帮助到一些人。

(请注意,在有人对我说学究气之前,是的,c++标准确实说指针表示内存地址。但它并没有说“指针是内存地址,而且只是内存地址,可以与内存地址互换使用或认为”。区别很重要)

这种混淆来自于在“指针”概念中混合在一起的多个抽象层。程序员不会对Java/Python中的普通引用感到困惑,但指针的不同之处在于它们暴露了底层内存架构的特征。

清晰地分离抽象层是一个很好的原则,而指针做不到这一点。

我认为,使指针难以学习的原因是,直到你熟悉了指针的概念,即“在这个内存位置是一组表示int型,double型,字符等的位”。

当你第一次看到一个指针时,你并不知道那个内存位置上有什么。“什么意思,里面有地址?”

我不同意“要么得到要么得不到”的观点。

当你开始发现它们的真正用途时(比如不要将大结构传递到函数中),它们就会变得更容易理解。

I think that the main reason that people have trouble with it is because it's generally not taught in an interesting and engaging manner. I'd like to see a lecturer get 10 volunteers from the crowd and give them a 1 meter ruler each, get them to stand around in a certain configuration and use the rulers to point at each other. Then show pointer arithmetic by moving people around (and where they point their rulers). It'd be a simple but effective (and above all memorable) way of showing the concepts without getting too bogged down in the mechanics.

一旦你学了C和c++,对某些人来说似乎就更难了。我不确定这是因为他们最终把他们没有正确掌握的理论应用到实践中,还是因为在这些语言中指针操作天生就更难。我不太记得我自己的转变,但我知道Pascal中的指针,然后转到C,完全迷失了。

邮政信箱号码。

它是一条信息,允许你访问其他东西。

(如果你计算邮政信箱号码,你可能会有问题,因为信进了错误的信箱。如果有人搬到另一个州——没有转发地址——你就有一个悬浮指针。另一方面,如果邮局转发邮件,那么你就有了指向指针的指针。)