大清早收到消息,好久前写的帖子(链接)下,有人问我问题:
原函数是这样的:
void Attach(int c, int e, Polynomial *pRear){
Polynomial P;
P = (Polynomial)malloc(sizeof(struct PolyNode));
P->coef=c;
P->expon=e;
P->link = NULL;
(*pRear)->link = P;
*pRear=P;
}
Attach(P1->coef, P1->expon, &rear);
他问,为什么要写成指针呢?写成下面这样不好吗?
void Attach(int c, int e, Polynomial pRear){
Polynomial P;
P = (Polynomial)malloc(sizeof(struct PolyNode));
P->coef=c;
P->expon=e;
P->link = NULL;
pRear->link = P;
pRear=P;
}
Attach(P1->coef, P1->expon, rear);
原因很简单,我做出的解答如下:
(1)首先明确 pRear
是一个指针,指向一个结点,那 pRear
本身就是一个地址变量;
(2)其次,明确 C
中都是传值调用。
在你的 Attach(P1->coef, P1->expon, rear)
中:
pRear->link = P;
上面这句话本身是没有问题的,可以对 link 进行赋值。
pRear=P;
但是这句话就不能起到赋值的效果,因为:
- 调用 Attach(P1->coef, P1->expon, rear) 时,将rear的值(因为
rear
是一个指针,所以其值是一个地址变量)赋值一份,给局部变量pRear赋上 - 此时 pRear 中保存地址变量,但其本身并不是指向 *rear 的指针;
- 换句话说,如果 pRear 的值改变,那么不对 rear 造成影响。
- 因此,想要改变 rear 的值,应该将 rear 的地址传入,而非将其本身。
这就涉及到一个基础问题:C/C++中,如何理解传值引用与调用引用?
有很多高手做了很精简凝练的回答,比如下面这个:
链接:只需要记住一句话,传值引用一般就是生成一个临时对象,而引用调用是调用参数本身。
说得对,且对于初学者而言这种理解再好不过。但通过一段时间的深入学习你会发现,所谓“传值引用”与“调用引用”其实是一回事。
对于“传值引用”,假设我们有如下代码:
int x = 0;
int foo(int x):
x = 10;
y = 20;
return y
则调用了 foo(x)
后,x
的值不变,还是 0
。
但若是“调用引用”,假设我们有如下代码:
int x = 0;
int foo(int *p):
*p = 10;
y = 20;
return y
则调用了 foo(&x)
后,x
的值变化为 10
。
为什么要加 &
与 *
这么多奇奇怪怪的符号?那就要牵扯到“指针”这个概念了。计算机中,每个变量都要有一个“住址”,就可以理解为变量的“地址”。
小明住在南开路92号,在计算机中的表达为:南开路92号(指针)指向小明(变量)。
在我们的例子中, &x
表示的是 x
的地址; int foo(int *p)
表示的是把一个指向 int
类型的指针 p
传入;*p
表示让“ p
本身是一个地址(指针)的前提下, p
所指向的东西”; *p=10
表示让这个地址所指向的变量赋值整数 10
。
可以看出,对于函数的传参,都是复制该参数的值,然后再传入,即都是“传值引用”。
之所以能做到“调用引用”,是因为对变量的指针进行了“传值引用”,指针的值被赋值,但是复制后其指向的依然是我们要修改的变量。