这是画一些照片的好地方。当你写
int* a = (int*) malloc(2 * sizeof(int));
您会得到如下所示的设置:
+---------+ +---------+---------+
| addr X | ---> | ????? | ????? |
+---------+ +---------+---------+
pointer a
in main
为a[0] 和a[1] 赋值后,如下所示:
+---------+ +---------+---------+
| addr X | ---> | 1 | 2 |
+---------+ +---------+---------+
pointer a
in main
现在,假设您致电 inc(a)。这会将指针a 的副本传递给inc 函数。由于指针是唯一被复制的东西,现在看起来像这样:
+---------+ +---------+---------+
| addr X | ---> | 1 | 2 |
+---------+ +---------+---------+
pointer a ^
in main |
|
+---------+ |
| addr X |-----------+
+---------+
pointer a
in inc
请注意,现在有两个名为 a 的指针,但它们不是同一个指针。这就像如果你有两个朋友叫 Zoe - 他们有相同的名字,但他们不是同一个人。
在inc,你写的
a++;
这意味着“将指针 a 前进以指向它当前指向的 int 之后的下一个 int。”这看起来像这样:
+---------+ +---------+---------+
| addr X | ---> | 1 | 2 |
+---------+ +---------+---------+
pointer a ^
in main |
|
+---------+ |
| addr Y |---------------------+
+---------+
pointer a
in inc
注意main 中的a 没有改变,因为我们正在操作a 的副本。再次回想一下 Zoe 的类比——如果你和一个叫 Zoe 的人交谈,这并不意味着你和另一个叫 Zoe 的人交谈。结果,当inc 返回时,a 的副本消失在以太中,我们只剩下这个:
+---------+ +---------+---------+
| addr X | ---> | 1 | 2 |
+---------+ +---------+---------+
pointer a
in main
由于指针没有改变,这就是为什么您在调用inc 之前和之后看到相同的值。
但是调用change 的工作方式不同。当您最初调用change 时,情况如下所示:
+---------+ +---------+---------+
| addr X | ---> | 1 | 2 |
+---------+ +---------+---------+
pointer a ^
in main |
|
+---------+ |
| addr X |-----------+
+---------+
pointer a
in change
当你现在写作时
a[0] = 2;
你是说“跟随名为 a 的指针,看看你在哪里结束,并将值 2 放在那里。这意味着我们看到以下内容:
+---------+ +---------+---------+
| addr X | ---> | 2 | 2 |
+---------+ +---------+---------+
pointer a ^
in main |
|
+---------+ |
| addr X |-----------+
+---------+
pointer a
in change
写a[1] = 3 也意味着“跟随名为a 的指针,在你找到的索引中找到1 处的元素,并将其替换为3。这给出了以下内容:
+---------+ +---------+---------+
| addr X | ---> | 2 | 3 |
+---------+ +---------+---------+
pointer a ^
in main |
|
+---------+ |
| addr X |-----------+
+---------+
pointer a
in change
现在,change 返回后,我们又回到了main。 main 中的 a 指针没有改变——它仍然在同一个地方寻找——但是它指向的数组的值已经改变了。
+---------+ +---------+---------+
| addr X | ---> | 2 | 3 |
+---------+ +---------+---------+
pointer a
in main
总结一下:
- 指针在 C 中按值传递,这意味着如果将指针传递给函数,则传递的是指针的副本。
- 因此,如果将指针作为参数的函数更改指针指向的位置,这将不会影响调用函数。
- 但是,如果一个函数改变了指向的内容,这将反映在调用者中。