这天小阿杰又在看C数据结构——
顺序表中几个传参的小小的内容引起了小阿杰大大的疑惑:(教材为严蔚敏老师的《数据结构(C语言版 第2版)》)
可怜的小阿杰当时只知道&取地址……后来查阅资料才对其中略知一二,那咱们下面就来唠唠。
顺便提一下,引用&只在C++中有,C语言中并没有什么引用&,只有取地址&,此处应为演示方便而使用
首先说这个指针和取地址,示例如下:
1 int main() { 2 int num = 3; 3 int* p ; //声明一个指针变量p 4 p= # // 将变量num的地址取出来,存到指针p中 5 printf("%d 的地址是 %p\n", num, p); 6 return 0; 7 }
输出:
3 的地址是 0x7ffeefbff3ac
然后看这个解引用,先上示例:
1 int main(){ 2 int num = 7; 3 int* p = # 4 printf("数值%d所在的地址是 %p\n", num, p); 5 printf("指针p指向的地址为 %p , 该地址上保存的值为%d\n", p, *p); 6 *p = 100; 7 printf("指针p指向的地址为 %p , 该地址上保存的值为%d\n", p, num); 8 return 0; 9 }
结果:
数值7所在的地址是 0x7ffeefbff3b8 指针p所指向的地址为 0x7ffeefbff3b8 , 该地址上所保存的值为7 指针p所指向的地址为 0x7ffeefbff3b8 , 该地址上所保存的值为100
其实这里*p和num等价的,个人认为这个“解引用”也许改叫“取值”会更形象一点(),这样的操作,直接顺着地址修改了原本的值,有点“顺藤摸瓜”的意思嘿嘿嘿。
插一句嘴,也可以让指针p指向别的变量的地址,比如:
1 int main(void) 2 { 3 int num = 7, another = -5; 4 int *p = # 5 p = &another; 6 printf("%d\n", *p);//此时p指向了another,所以输出了another的值,即-5 7 return 0; 8 }
这时候咱们来介绍以下引用,最简单来说,“引用”就是起别名,我们来看例子:
1 int main() 2 { 3 int val = 7, val2 = 999; 4 int &refval = val, &refval2 = val2; //引用必须要初始化,使其绑定到一个变量上 5 //修改引用的值将改变其所绑定的变量的值 6 refval = -12; 7 printf("%d %d\n", val, refval);//-12,refval的值和val一样 8 9 //将引用b赋值给引用a将改变引用a所绑定的变量的值, 10 //引用一但初始化(绑定),将始终绑定到同一个特定对象上,无法绑定到另一个对象上 11 refval = refval2; 12 printf("%d %d\n", val, refval);//999 13 return 0; 14 }
其结果为:
-12 -12 999 999
小阿杰这里有个形象恰当的比喻(bushi),比方说你有一个全名,还有一个昵称,有人骂你,不管骂的是你的全名还是昵称,被骂的(骂这个动作的承受对象)都是你本人。
(没有冒犯,纯属举例,如果要骂的话,各位读者大大就骂小阿杰吧qaq)
到这里的话,基本的知识我们就了解了,那回归我们的正题,对于前面图片中的那个“时隐时现”的“&”,我们又该如何理解呢?
对于 SqList&L
这样的函数参数,它使用了引用传递方式。这意味着函数内部对参数的修改会影响到函数外部传入的实参。修改参数的操作可以直接影响到原始的数据。
而对于 SqList L
这样的函数参数,它使用了值传递方式。这意味着函数内部对参数的修改不会影响到函数外部传入的实参。函数会对参数进行一次拷贝,并在函数内部操作该拷贝的副本,而不是直接修改原始数据。
下面咱们来看示例:
1 #include <stdio.h> 2 3 typedef struct { 4 int data[5]; 5 int length; 6 } SqList; 7 8 // 使用引用传递修改参数 9 void modifyByReference(SqList& L) { 10 L.length = 0; 11 for (int i = 0; i < 5; i++) { 12 L.data[i] = i; 13 } 14 } 15 16 // 使用值传递修改参数的副本 17 void modifyByValue(SqList L) { 18 L.length = 0; 19 for (int i = 0; i < 5; i++) { 20 L.data[i] = i; 21 } 22 } 23 24 int main() { 25 SqList myList = {{1, 2, 3, 4, 5}, 5}; 26 27 // 使用引用传递修改 28 modifyByReference(myList); 29 printf("Modified by reference: "); 30 for (int i = 0; i < myList.length; i++) { 31 printf("%d ", myList.data[i]); 32 } 33 printf("\n"); 34 35 // 使用值传递修改副本 36 modifyByValue(myList); 37 printf("Modified by value: "); 38 for (int i = 0; i < myList.length; i++) { 39 printf("%d ", myList.data[i]); 40 } 41 printf("\n"); 42 43 return 0; 44 }
这样的话我们得到的输出结果是:
Modified by reference: 0 1 2 3 4 Modified by value: 1 2 3 4 5
可以看到,在使用引用传递时,函数内部对参数的修改直接影响到了函数外部传入的实参 myList
。而在使用值传递时,函数内部对参数的修改只会影响到函数内部的副本,不会改变原始的 myList
对象。
经过这么一番折腾,小阿杰对这个引用&符终于有点眉目了,可以心安理得地摆大烂了嘻嘻嘻。
那咱们今天就先唠到这里吧,再见(灰灰)!
参考文章:指针(*)、取地址(&)、解引用(*)与引用(&)_指针取地址_Adenialzz的博客-CSDN博客
关于被调函数形参:SqList L、SqList &L、SqList *L 的区别_c语言sqlist l_Uncertainty!!的博客-CSDN博客
标签:num,int,地址,初识,引用,printf,数据结构,指针 From: https://www.cnblogs.com/JerryWayne7/p/17579325.html