传值、传地址、传引用
这部分的代码是在https://blog.youkuaiyun.com/weixin_44309097/article/details/124086049的代码基础上改的。
传值
#include <stdio.h>
#include <stdlib.h>
void Exchg1(int x, int y) // 定义中的x,y变量被称为Exchg1函数的形式参数
{
int tmp;
tmp = x;
x = y;
y = tmp;
printf("x,y的地址分别是:%p,%p.\n",&x,&y);
printf("x = %d, y = %d.\n", x, y);
}
int main()
{
int a = 4,b = 6;
printf("a,b的地址分别是:%p,%p.\n",&a,&b);
Exchg1(a, b); //a,b 变量为 Exchg1 函数的实际参数。
printf("a = %d, b = %d.\n", a, b); //输出 a=4,b=6.
return 0;
}
输出结果:
a,b的地址分别是:000000000062FE1C,000000000062FE18.
x,y的地址分别是:000000000062FDF0,000000000062FDF8.
x = 6, y = 4.
a = 4, b = 6.
可以看出Exchg1(a, b);只是将a,b的值复制了一份到Exchg1函数内的局部变量x,y,所以可以看见a的地址并不与x的地址相同。
故x,y值的改变对a,b的值没有影响。
传地址
传地址是一种特殊的传值,区别在于传递的值是地址。
#include <stdio.h>
#include <stdlib.h>
void Exchg2(int *px, int *py)
{
int tmp = *px;
*px = *py;
*py = tmp;
printf("px,py的值分别是:%p,%p.\n",px,py);
printf("px,py的地址分别是:%p,%p.\n",&px,&py);
printf("*px = %d, *py = %d.\n", *px, *py);
}
int main()
{
int a = 4;
int b = 6;
printf("a,b的地址分别是:%p,%p.\n",&a,&b);
Exchg2(&a, &b);
printf("a = %d, b = %d.\n", a, b);
return 0;
}
它的输出结果是:
a,b的地址分别是:000000000062FE1C,000000000062FE18.
px,py的值分别是:000000000062FE1C,000000000062FE18.
px,py的地址分别是:000000000062FDF0,000000000062FDF8.
*px = 6, *py = 4.
a = 6, b = 4.
void Exchg2(int *px, int *py)
这里,定义了两个int*类型的地址变量px,py,用来存储int类型变量的地址。也可以说是定义了两个指向int类型的指针。
调用函数时,是将a,b的地址复制一份到px,py,因此a和px,b和py不是同一个变量。从输出结果也可以看出这一点,a的地址并不与px的地址相同,但a的地址被赋值给了px变量。
Exchg2(&a, &b); //定义的是地址变量,所以赋值用的也是地址
这里传入的也是int类型变量的地址。将&a,&b赋值给了px,py
因为传入的是地址,所以*px和a的值是存储在同一个地址空间&a的值,因此*px改变,a的值也会改变
传引用
C语言不支持引用传递,传引用是C++的功能
#include <stdio.h>
#include <stdlib.h>
void Exchg3(int &x, int &y)// 注意定义处的形式参数的格式与值传递不同
{
int tmp = x;
x = y;
y = tmp;
printf("x,y的地址分别是:%p,%p.\n",&x,&y);
printf("x = %d, y = %d.\n", x, y);
}
int main()
{
int a = 4;
int b = 6;
printf("a,b的地址分别是:%p,%p.\n",&a,&b);
Exchg3(a, b); /*注意:这里调用方式与值传递一样*/
printf("a = %d, b = %d.\n", a, b);
return 0;
}
输出结果:
a,b的地址分别是:000000000062FE1C,000000000062FE18.
x,y的地址分别是:000000000062FE1C,000000000062FE18.
x = 6, y = 4.
a = 6, b = 4.
Exchg3(int &x, int &y)
这里是定义了两个int引用类型变量,x,y。x和y都是引用类型(int* p,一般说p是int类型指针,*p是int类型引用)
Exchg3(a, b);//定义的是int引用,所以赋值的也是int引用或int类型变量
引用传递 Exchg3(a, b)函数里是用 a、b 分别代替了 x、y。函数里操作的就是 a、b 变量的本身,因此 a、b的值可在函数里被修改的。
从输出结果也可以看出,a和x的地址一样,它们就是同一个变量。
LNode* L和 LNode* &L的区别
请查看https://blog.youkuaiyun.com/weixin_43624310/article/details/129200615的代码。
这里我懒得写代码了,是基于他的代码的基础上理解的
理解了前面的内容,现在我们可以来解决这个问题了,链表中的传引用和传值。
另外,请记住,不管是多么复杂的变量,比如LNode*,把它视为一个整体,它是一个与int类型一样的东西,都是变量类型而已。
就像初中数学时老师教的,将变量(x+y)视作一个整体看待一样。它们并没有本质区别,究其本质,而非细枝末节。
传引用:
定义函数时:pr(LNode* &L)
调用时:LNode* L=NULL; pr(L);//定义函数时定义的的是LNode*引用类型,传的也是LNode*类型
由于是传引用,因此在链表的增删改查中,L在pr()函数内改变指向,函数外也随之改变
传值:
定义函数时:LNode* pr(LNode* L)
调用时:LNode* L=NULL,L=pr(L);
由于是传值,因此L在pr()函数内改变指向,函数外是不会发生改变的。
但L本身是一个地址类型(指针类型),所以将L的值,也就是这个地址传进去,pr函数内外L所指向的结点是同一个,
故函数内外的L.data,与L.nex变量是同一个,所以L.data与L.next是会随着函数内部修改值而发生改变的。
注:
pr函数中完成的事情:
L=(LNode*)malloc(sizeof(LNode));
L->data=10;