⚙️ 第四章 让内存化方为圆
📄 一句话概括

指针就是装地址的变量:普通变量装数据,指针变量装【数据在哪儿】;解引用,就是拿着门牌号去找人。

📝 本节和前面几节的关系

4.2 讲的是【怎么理解地址】,这一节讲【把地址当成数据来用】。

一、普通变量和指针变量的区别

普通变量里装的是数据本身:n = 42,格子 100 号里就写着 42。 指针变量里装的是地址:p 自己的格子(104 号)里写着 100——也就是 n 在哪儿。 一句话:指针不是什么高级东西,它只是一个值恰好是地址的普通变量。 所以指针能参与运算、能比较大小、能放进数组——跟别的变量没有两样。

二、两个动作:取地址与解引用

教材用 C 语言演示,只有两个符号要记: &a 是取地址——问出 a 住在哪儿。 *p 是解引用——顺着 p 里记的地址,去把那格的数据取出来。 于是 p = &a; 之后,*p 和 a 指的是同一个格子——改哪个都算改它。

三、为什么非要用它

一、让函数改得动外面的变量。 C 语言的参数是按值传的,直接把变量传进去改不了;传地址就行。 二、处理大小不定的数据。 与其把一大块数据搬来搬去,不如只传它开头的地址。 三、把数据串起来。 链表、树、图全靠【存着下一个的地址】才连得起来——那是 4.6、4.7 的主角。 所以指针不是炫技,它是唯一能让程序【指来指去】的工具。

四、Python 里没有指针,但有引用

Python 把指针藏起来了,你看到的是引用:变量指向某个对象,赋值只是让两个名字指向同一份数据。 b = a 之后改 b,a 也跟着变——因为本来就是同一份。 c = a[:] 是新复制的一份,改它就不影响 a。 所以【浅拷贝还是深拷贝】【函数里改了列表外面为什么也变了】这类问题,根子都在这一节。

五、动手 Demo:指针其实很简单

普通变量装数据,指针变量装地址——就这么点差别。 Python 没有指针语法,但引用就是它的影子。

a = [1, 2, 3]
b = a          # b 和 a 指的是同一份数据
c = a[:]       # c 是新复制的一份
b.append(4)
print("a =", a)
print("b =", b)
print("c =", c)

实跑输出:

--------------------------------------------------------------------
指针其实很简单
--------------------------------------------------------------------

**指针就是【装地址的变量】。** 普通变量装数据,指针变量装地址。

  把内存画成一张表看看(地址是模拟的,只为对照):

  变量     它占的地址     里面装的是什么
  ----------------------------------------------------
  n        100            数据 42
  p        104            地址 100(也就是 n 在哪儿)

  读 p 得到 100,再拿 100 去内存里找——就取到了 42。
  **所谓【解引用】,就是这么一回找门牌号的事。**

  Python 里没有指针这个语法,但**引用就是它的影子**:

    a = [1, 2, 3]
    b = a           # b 和 a 指的是同一份数据
    c = a[:]        # c 是新复制的一份
    b.append(4)
    a = [1, 2, 3, 4]   b = [1, 2, 3, 4]   c = [1, 2, 3]

  **改 b 会连 a 一起动,改 c 不会——差别就在【是不是同一份】。**
  那些【浅拷贝还是深拷贝】的问题,根子都在这儿。

改 b 连 a 一起动,改 c 不影响 a——差别就在是不是同一份。 回头把指针的几个麻烦(野指针、内存泄漏)也理解成【地址指错了地方】,就不难了。

30 秒实验

  1. 写一个函数,接收列表并往里加一个元素,看看外面的列表变不变。
  2. 把列表换成整数再试一次,对比结果——这就是【传值】和【传地址】的差别。

常见误区

  1. 以为指针是高级特性。它只是个装地址的普通变量。
  2. 把 & 和 * 记反。&a 取地址,*p 顺着地址取数据。
自测三问(点开对答案) 1. 指针变量里装的是什么? —— 另一个变量(或数据)的地址。 2. 取地址和解引用分别怎么写? —— `&a` 取 a 的地址;`*p` 顺着 p 里的地址把数据取出来。 3. Python 的引用和指针是什么关系? —— Python 把指针藏起来了,引用就是它的表现——两个名字可以指向同一份数据。

相关笔记