引用传递和值传递以及链表中的LinkList L、LinkList *L、LinkList &L

引用传递和值传递以及链表中的LinkList L、LinkList *L、LinkList &L函数参数传递的两种方式为值传递和引用传递 1 传值方式传参 c 语言是按值传递的 在函数中被传递的参数的本身 实参 是不能被修改的 参数 x 传进去的时候会被复制了一份 copy 此后的修改都是在临时变量 copy 上 出了函数体 copy 被销毁 x 还是原来的 x 根本就没有被修改过 所以对变量 x 的修改无效 如果想要修改传入的参数 有两种方法 传地址 传入 x 的地址 也就是将指向 x 的指针作为参数进行传

函数参数传递的两种方式为值传递和引用传递

1.传值方式传参

c语言是按值传递的,在函数中被传递的参数的本身(实参)是不能被修改的!参数x传进去的时候会被复制了一份copy,此后的修改都是在临时变量copy上,出了函数体copy被销毁,x还是原来的x,根本就没有被修改过,所以对变量x的修改无效。

如果想要修改传入的参数,有两种方法:

传地址,传入x的地址,也就是将指向x的指针作为参数进行传递,【指针参数传递本质上是值传递,它所传递的是一个地址值】int f(int *x); f(&x); 指针传进去被复制了一份copy,x的指针的copy指向的内容也是x,对指针的copy的修改也就是修改了x的内容。 对于①来讲,在函数中如果传递的是指针,那么只能修改指针指向的内容,不能修改指针本身;如果想要修改指针本身,要么在再加一级指针,要么用引用&。

引用传参 ,引用传参往往要比值传参高效,因为它是直接将x作为参数传入进去,而少了对x进行复制这部分的开销,既然传入进去的是x,那么对x的修改肯定也生效。

2.引用方式传参

引用可以被理解为变量的一个别名,但这依旧是原变量,如果在函数内对该变量进行修改的话,在外部该变量也会相应被修改。一定要先有原变量,才能有原变量的别名,故引用一定要赋初值,写成int &a=一个已存在的值的形式。

int a=11; int &b=a; b=9 在这时输出a的值发现a=9。 

【比如:我的名字叫王,别名叫王哥,我在函数里传入的参数为王哥,在函数内部我修改了王哥的体重,那么在调用函数时,王的体重也被修改了。】

引用声明后使用方式和原变量一样(用指针的话要加一个取值的操作)

3.通过一段代码运行进一步理解传指针(包括二级指针)和传指针的引用

①函数传递的是指针变量的值——即该指针所指向的变量的地址,只能改变指针所指向变量的值,而不能改变指针本身的值。

#include 
  
    #include 
   
     typedef struct LNode{ int data; struct LNode *next; }LNode,*LinkList; void CreateList(LNode *header){ header=(LNode*)malloc(sizeof(LNode)); header->data=11; header->next=NULL; } int main(){ LinkList head=NULL; CreateList(head); if(head!=NULL){ printf("%d\n",head->data);//什么都没有输出 } free(head); return 0; } 
    
  

②传递指针的地址,便可以修改指针本身的内容

#include 
  
    #include 
   
     typedef struct LNode{ int data; struct LNode *next; }LNode,*LinkList; //初始化链表,函数调用完毕后,L会指向一个空的链表,即会改变指针的值,所以要用header //header不仅能修改指针所指向变量的值,也能够修改指针本身的内容 void CreateList(LNode header){ //(LinkList *header) (*header)=(LNode*)malloc(sizeof(LNode));//(LinkList)malloc(sizeof(LNode)); (*header)->data=11; (*header)->next=NULL; } int main(){ LinkList head=NULL; CreateList(&head);//传递指针本身的地址 if(head!=NULL){ printf("%d\n",head->data);//11 } free(head); return 0; } 
    
  

③(LinkList &header)这里的header其实是传入指针head的别名

#include 
  
    #include 
   
     typedef struct LNode{ int data; struct LNode *next; }LNode,*LinkList; //header其实是传入指针head的别名 void CreateList(LinkList &header){ //参数也可写成(LNode *&header) header=(LNode*)malloc(sizeof(LNode));//(LinkList)malloc(sizeof(LNode)); header->data=11; header->next=NULL; } int main(){ LinkList head=NULL; CreateList(head); if(head!=NULL){ printf("%d\n",head->data);//11 } free(head); return 0; } 
    
  

4.总结

其实指针类型和基本类型(比如int)来说,并没有本质上的差别。示例 :int x;LNode *L; (LNode为结构体)

  • 在传值方式传参时,对于基本类型:函数参数为int x,调用函数传入x;对于指针:函数参数为LNode *,调用函数时传入L
  • 在地址传递时,对于基本类型:函数参数为int *x,调用函数传入&x;对于指针:函数参数为LNode ,调用函数时传入&L。    
  • 在引用方式传参,对于基本类型:函数参数为int  &x,调用函数传入x;对于指针:函数参数为LNode* &L(或LinkList &L ),调用函数时传入&L。   

当你传值时,只可以引用值而不可以改变值,但传值引用时,可以改变值; 当你传指针时,只可以改变指针所指的内容,不可以改变指针本身,但传指针引用时,即可以改变指针所指的内容,又可以改变指针本身

补充注意点:

①在定义函数时函数括号中的变量名成为形式参数,简称形参或虚拟参数;在主调函数中调用一个函数时,该函数括号中的参数名称为实际参数,简称实参,实参可以是常量、变量或表达式。

②C语言中实参和形参之间的额数据传递是单向的“值传递”,单向传递,只能由实参传给形参,反之不能。

③被调用函数的形参只有函数被调用时才会临时分配存储单元,一旦调用结束占用的内存便会被释放。

④”按值传递“中包括值传递和指针传递(指针传递参数本质上是值传递的方式,它所传递的是一个地址值),传递的都是实参的一个拷贝;虽然指针传递可以通过改变地址值来改变指针所指向的变量的值,但是不能改变指针本身的值。

⑤对于指针的引用类似于二级指针,但是也有一定的区别:无论你传值还是传指针,函数都会生成一个临时变量, 但传引用时,不会生成临时变量,不进行返回值copy等,速度快。

⑥关于引用传递和指针传递(本质是值【地址值】传递):

· 相同点:都是地址的概念

指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。

· 不同点: 

  • 指针是一个实体(也可以理解为替身);引用只是一个别名(本体的另一个名字)
  • 引用只能在定义时被初始化一次,之后不可改变;指针可以修改;
  • 引用不能为空;指针可以为空;
  • sizeof 引用,得到的是所指向变量的大小;sizeof 指针,得到的是指针的大小;
  • 指针 ++,意义为 指针的地址自增;引用++则是 所指变量自增;
  • 引用是类型安全的,引用过程会进行类型检查;指针不会进行安全检查;
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/204595.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午7:58
下一篇 2026年3月19日 下午7:59


相关推荐

  • Java写俄罗斯方块,了解一下

    Java写俄罗斯方块,了解一下Java 俄罗斯方块目录 Java 俄罗斯方块 一 游戏场景篇 Java 俄罗斯方块 二 游戏操作与逻辑篇简要分析 俄罗斯方块的规则在这里就不细说了 大家都知道 控制方块的移动 到底即停 当方块能填满一行时 便消除那一行的方块 并计分 我们将用 JPanel 来完成整个游戏的制作 首先我们来看看游戏运行时的图片 游戏图片 上图是游戏制作过程中我

    2026年3月19日
    1
  • sql中的升序和降序的区别_数据库中的降序

    sql中的升序和降序的区别_数据库中的降序select*from表名orderby字段名desc//降序select*from表名orderby字段名asc//升序降序:select*fromemporderbyempiddesc;//按empid这一列的值降序来排列查询出emp表升序:select*fromemporderbyag…

    2025年8月19日
    4
  • python中random函数的使用方法 详解

    python中random函数的使用方法 详解#random各种使用方法importrandom#随机生成[0.1)的浮点数print("random():",random.random())#随机生成1000-9999之间的整数print("randint(1000,9999):",random.randint(1000,9999))#随机生成0-20之间的偶数print("randrange(0,21,2):"…

    2022年6月14日
    38
  • 【即梦AI教程】16.AIMV制作

    【即梦AI教程】16.AIMV制作

    2026年3月13日
    3
  • 马化腾:希望元宝 重现2015年微信红包时刻

    马化腾:希望元宝 重现2015年微信红包时刻

    2026年3月13日
    2
  • java 线程池面试题

    java 线程池面试题Java多线程面试问题 1.进程和线程之间有什么不同? 一个进程是一个独立(selfcontained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一个包含了不同的类和程序的单一进程。线程可以被称为轻量级进程。线程需要较少的资源来创建和驻留在进程中,并且可以共享进程中的资源。2.多线程编程的好处是什么?  在多线程程序中,多个线程被

    2022年5月25日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号