在数据结构与算法中|在数据结构与算法中 传值方式(C语言)

传值方式 前言

当初学顺序链表的时候,书上就出现了这样的语言,如下所示:
Status InitList_Sq(SqList &L) { //构造一个空的线性表L。 L.elem = (ElemType *)malloc(LIST_INIT_SIZE* sizeof(ElemType)); if(!L.elem)exit(OVERFLOW); L.length=0; L.listsize=LIST_INIT_SIZE; return OK; }

在数据结构与算法中|在数据结构与算法中 传值方式(C语言)
文章图片

这里面的&L第一遍看的时候想当然的认为是取了SqList结构体的L的地址,没有细想。然后又看到了这句。
Status GetElem(SqList L,int i,ElemType &e)//这根本就不是取地址符

这里的ElemType就是int的类型
【在数据结构与算法中|在数据结构与算法中 传值方式(C语言)】那么可以写成如下这种方法
Status GetElem(SqList L,int i,int &e)

这样整个倒是显得非常奇怪
那么我们类比这样的形式
int *a,*b; /* 定义了两个整型的指针 */ int **a, **b; /* 定义了整型指针的指针 */

//那么难道说是定义了整型变量为地址的变量e int &e;

那么我们看下面他写的这个东西:
在数据结构与算法中|在数据结构与算法中 传值方式(C语言)
文章图片

显然这里可以看出由于L指针指向的是ElemType类型,所以e是ElemType类型的。所以以上类比显然是不对的。
C/C++中的引用参数
查找了很多的资料发现,这个实际上是C++里的形参符号,必须要在跟在数据类型的后面使用。在函数内部对形参的操作都等同于直接操作原变量。
请看下面的例子
1.1 实参值不变
把实参的值传送给函数局部工作区相应的副本中,函数使用这个副本执行必要的功能。函数修改的是副本的值,实参的值不变。
#include void swap(float m,float n) { float temp; temp = m; m = n; n = temp; } void main() { float a,b; printf ("please enter the number of a and b ="); scanf("%f %f",&a,&b); swap (a,b); printf ("the number of a = %f, the number of b = %f",a,b); }

在数据结构与算法中|在数据结构与算法中 传值方式(C语言)
文章图片

可以看到,a与b的值并没有发生更换。
1.2传地址方式——指针变量做参数,形参变化影响实参
#include void swap(float *m,float *n) { float temp; temp = *m; //取指针变量内容 *m = *n; *n = temp; 1 } void main() { float a,b,*p1,*p2; printf ("please enter the number of a and b ="); scanf("%f %f",&a,&b); p1=&a; p2=&b; swap (p1,p2); printf ("the number of a = %f, the number of b = %f",a,b); }

在数据结构与算法中|在数据结构与算法中 传值方式(C语言)
文章图片

还有第二种方式
#include // 利用指针的经典解法 void swap(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; }void main() { int a = 1, b = 2; swap(&a,&b); printf("%d %d",a,b); }

在数据结构与算法中|在数据结构与算法中 传值方式(C语言)
文章图片

可以看到,形参变化影响实参
在数据结构与算法中|在数据结构与算法中 传值方式(C语言)
文章图片

形参变化不影响实参
#include void swap(float *a, float *b) { float *temp; temp = a; a = b; b = temp; }void main() { float a = 1, b = 2; swap(&a,&b); printf("%f %f",a,b); }

在数据结构与算法中|在数据结构与算法中 传值方式(C语言)
文章图片

可以发现ab值并没有发生变化
在数据结构与算法中|在数据结构与算法中 传值方式(C语言)
文章图片

1.4 传地址方式——数组名作参数
传递的是数组的首地址 概念:数组名就是数组首地址
对形参数组所做的任何改变都将反映到实参数组中
#include #include void sub(char *b)//在C++语言中也可以使用b[]来写 { strcpy(b,"world"); } void main() { char a[10] = "hello"; sub(a); //传数组首地址 printf("%s",a); }

在数据结构与算法中|在数据结构与算法中 传值方式(C语言)
文章图片

1.5 传地址方式——引用类型做参数
什么是引用?
引用:他用来给一个对象提供一个代替的名字
//运用了C++的语法 #include #include // 引用参数实现交换 void swap(int &a, int &b){ int temp; temp = a; a = b; b = temp; }// Using main to test int main(){ int a = 1, b = 2; swap(a,b); printf("%d %d\n",a,b); return 0; }

在数据结构与算法中|在数据结构与算法中 传值方式(C语言)
文章图片

有些文章说道,通过引用的方式传递给函数的是变量的地址,这种方式叫做地址传递方式,还提到这是和“值传递”十分不同的方式。
有些书说道:“引用实际上是取了个‘别名’”
还有的书和文章说道引用是比通过指针传递更加高效的方式,因为不需要开辟新的内存空间用来拷贝实参的地址。
那么SqList *&L和SqList *L的关系就能捋清楚了 可以参考1.2 传地址方式——指针变量做参数,形参变化影响实参
SqList *&L的情况 它的意思是,L是对List的引用,函数体内对L的操作,就相当于对Head的操作,所以这种情况下对L的更改才会发生到List上。
SqList *L的情况 当List指针作为函数参数传进去时,意为你要把指针List所指的地址值赋给指针L,(可以类比int类型,毕竟指针本质上也是一种数据类型)。这就意味着此时的实参List跟形参L并不是同一个指针,而是指向同一个地址的不同指针。所以你对L的操作并没有发生到List身上。达不到预期效果。
最后
C语言不存在“引用”的概念,符号“&”只是表示取地址,而C++才有“引用”的含义。
比如对于这段代码——
//C语言不存在“引用”的概念,符号“&”只是表示取地址,而C++才有“引用”的含义。 //比如对于这段代码—— #include int main() { int i = 0; int &j = i; }, /*使用gcc编译器编译会报错:”错误:expected identifier or ‘(’ before ‘&’ token“,但是使用g++编译就不会报错。*/

    推荐阅读