C语言函数传递指针参数的问题

解释C语言中的函数及其参数传递方式 如果函数不需要修改其参数的值,或者参数是较大的数据结构(例如结构体或数组),则通常使用值传递(对于结构体和数组,传递的是它们的副本的指针)。请注意,对于大型数据结构,直接通过值传递可能会导致性能问题,因为这将涉及大量的内存复制操作。在这种情况下,通常使用指针或引用(在C++中)来传递数据结构的地址,以避免不必要的复制。函数的参数列表指定了传递给函数的变量的类型和数量。参数传递是函数调用的一个重要部分,它涉及到将实际参数(也称为实参)的值传递给函数定义中的形式参数(也称为形参)。在上面的指针传递示例中, 阅读详情
C语言函数传递指针参数的问题

一个问题是,我们想用一个函数来对函数外的变量v进行操作,比如,我想在函数里稍微改变一下这个变量v的值,我们应该怎么做呢?又或者一个常见的例子,我想利用swap()函数交换两个变量a,b的值,我们应该怎么做呢(好吧,博主是觉得这个问题十分经典)。

如果你真的理解C语言中【函数】这个工具的本质,我想你稍微仔细的思考一下,可能就不会来查看博主的这篇文章,对函数来说,它所传递的任何参数仅仅是原来参数的一个拷贝,所以,对任何企图通过void swap(int a,int b)来交换a,b值或者想通过void alter(int v)来改变v的值,都是徒劳的。

C语言里,改变值只能通过指针(地址)方式进行传递,或许你会说传递数组不是也可以改变值么,实际上,传递数组就是传递指针(或许对数组来说,这个指针有点特别)//注意:C里没有引用,C++里才有

我们先来看一下有趣的swap函数,它用于交换a,b两个变量

code case 1

#include <stdio.h>
void swap(int a,int b)
{
    int temp=a;
    a=b;
    b=temp;
}
int main()
{
    int a=4,b=5;
    swap(a,b);
    printf("a = %d ,b = %d\n",a,b);
    return 0;
}


不出意料的,我们会知道这段代码其实并不能得到我们想要的结果,它并不能交换两个变量a,和b,的值,这是为什么?

我们不妨修改这段代码,在main()和swap()里分别打印a和b的地址,看看到底发生了什么;我们修改代码如下:
code case 2

#include <stdio.h>
void swap(int a,int b)
{
    printf("address in swap():%p %p\n",&a,&b);
    int temp=a;
    a=b;
    b=temp;
}
int main()
{
    int a=4,b=5;
    printf("address in main():%p %p\n",&a,&b);
    swap(a,b);
    printf("a = %d ,b = %d\n",a,b);
    return 0;
}


它的运行结果为:

address in main():0061FF2C 0061FF28
address in swap():0061FF10 0061FF14
a = 4 ,b = 5


显然,在两个函数里,它们的地址并不相同,这意味着,它们并不是相同的存储空间,改变swap里的值,实际上仅仅只改变了swap()里面的a和b的值罢了,一旦swap执行完,swap里的a和b的储存空间立即释放掉,对于main()里的a和b,没有半点影响。

那么在C语言里如何才能交换两个变量的值呢?
方法是通过指针传参,看下面的代码
code case 3

#include <stdio.h>
void swap(int *a,int *b)
{
    printf("address in swap():%p %p\n",a,b);
    int temp=*a;
    *a=*b;
    *b=temp;
}
int main()
{
    int a=4,b=5;
    printf("address in main():%p %p\n",&a,&b);
    swap(&a,&b);
    printf("a = %d ,b = %d\n",a,b);
    return 0;
}


运行结果为:

address in main():0061FF2C 0061FF28
address in swap():0061FF2C 0061FF28
a = 5 ,b = 4


这样,就把a,b的值交换了!
等等,我们分析一下它的原理,它究竟做了哪些变化呢,在swap函数里,我们将a和b的地址给了swap函数,作为形参,在swap函数中,a和b是指向两个int 类型的指针,它们接受了main里面a和b的地址,也就是a=&a (in main());b=&b (in main());所以对*a实际上就是对a(in main())操作啦;
那么,聪明的你肯定能想到,在swap()函数里变量a和b的地址肯定和main里a和b的地址是不同的,swap里的a,b的地址是指针的地址(在swap里a,b是指针),而它们的值是在main()里面a和b的地址;
我们不妨打印一下swap里a,b和地址就明白了;
code case 4

#include <stdio.h>
void swap(int *a,int *b)
{
    printf("address in swap(),the value of a and b:%p %p\n",a,b);
    printf("address in swap(),the address of a and b:%p %p\n",&a,&b);
    int temp=*a;
    *a=*b;
    *b=temp;
}
int main()
{
    int a=4,b=5;
    printf("address in main(),the address of a and b:%p %p\n",&a,&b);
    swap(&a,&b);
    printf("a = %d ,b = %d\n",a,b);
    return 0;
}


运行结果:

address in main(),the address of a and b:0061FF2C 0061FF28
address in swap(),the value of a and b:0061FF2C 0061FF28
address in swap(),the address of a and b:0061FF10 0061FF14
a = 5 ,b = 4

通过结果我们知道,在swap里,指针a和b的值和main()里的a和b的地址是一样的,那么对*a进行的各种赋值实际上就是对main()里的a的各种操作,它们代表同一储存空间的的值;但是对swap里的a,和b的地址,和main里的是不一样的,这是显然的,a只是一个容纳&a地址的变量罢了,它是swap里重新分配的一块内存,并且,它的类型和main里的a,b类型完全不同,它是一个指针类型;

用比喻的方法来讲,在多行书架上,每行各自放了一本书,现在我想把a,b这两本书交换一下位置,我想让你帮我交换一下,你要怎么做呢?好了,我告诉你a书在第一行书架上,b在第四行书架上,现在,你可以做了吧,你首先会取出第一行的a书,将其拿出放在左手,然后用右手取出位于第四行的b书,放在第一行上,再将位于左手上的a书放到第四行上,至此,交换完成。
仔细想想,在这个过程中你不就相当于充当了swap这个函数的作用吗?我告诉了你a,b的地址,你真正交换了它

当然,我想探讨的并不是只有这些,在文章一开始,我就引入了这样的话题,我们先看一下这段代码问题:

#include <stdio.h>
#include <malloc.h>
typedef struct LNode
{
    int data;
    struct LNode *next;
}LNode;
void InitLinkList(LNode *L)
{
    L=(LNode *)malloc(sizeof(LNode));
    L->data=0;
    L->next=NULL;
}
int main()
{
    LNode *L=NULL;
    InitLinkList(L);
    printf("%p\n",L);
    return 0;
}


问:该代码能否正确初始化一个链表头结点?
我想,如果你能正确理解前面的几个例子,那么,你的答案一定回答的是NO,该InitLinkList并不能真正初始化一个链表头结点,在函数里我们的确是给L分配了内存,初始化了结点,但是,InitLinkList()里的L并不是main()里的L,虽然名称是一样的,但是InitLinks()的L是局部的(所以,其实你写成a,b,c,d都没关系),传进来的只是一个LNode*副本,这个副本和外面的L的内容是一样的,但是变量不是同一个,当这个子函数执行完后,main()里的L还是原来的L。
(注意!在InitLinkList函数中通过malloc分配的内存是通过堆来划分的,这意味着函数调用完毕后,内存不能自动释放,将会造成内存泄漏,并且,此代码中malloc申请的内存是悬浮的)

但是,在大多数时候,我们却的确是需要这样一个函数来为我们做这些事情,那么,应该怎么修改呢?
修改代码如下

#include <stdio.h>
#include <malloc.h>
typedef struct LNode
{
    int data;
    struct LNode *next;
}LNode;
LNode * InitLinkList(LNode *L)
{
    L=(LNode *)malloc(sizeof(LNode));
    L->data=0;
    L->next=NULL;
    return L;
}
int main()
{
    LNode *L=NULL;
    L=InitLinkList(L);
    printf("%p\n",L);
    return 0;
}


运行结果

006D1588
  • 1

改过后的InitLinkList初始化了头结点,并把生成节点的地址传递给上一层的main中的L,所以得到了正确的结果
(实际上,写成InitLinkList(LNode *L)可能不是一种必要的方式,完全可以写成void,这两者是等价的)

对比交换a,b值那样,我们也可以这样改

#include <stdio.h>
#include <malloc.h>
typedef struct LNode
{
    int data;
    struct LNode *next;
}LNode;
void InitLinkList(LNode **L)
{
    (*L)=(LNode *)malloc(sizeof(LNode));
    (*L)->data=0;
    (*L)->next=NULL;
}
int main()
{
    LNode *L=NULL;
    InitLinkList(&L);
    printf("%p\n",L);
    return 0;
}


运行结果

006B1588
  • 1

(注:采用此种方式是及其复杂的,因为这是一个二级指针,会增加理解难度,所幸的是,c++中的引用,可以避免这个问题)

想一下,为什么,
在swap(int *a,int *b)中,a,b是指针变量,它们自身有个地址&a,&b,a,b的内容是存放传递过来的变量地址(也即是main()里a,b的地址),用*a和*b就是取当前所存放地址的值,也就是说,a,b指向main里a,b的内存块地址,*a和*b相当于是直接对main()里的a,b其操作,所以能到达交换(改变值)的目的是显然的。
在这里main里的L是一个指针类型,本身就指向某块内存,而L这个变量的地址作为内容传递给initLinkList()函数,那么子函数里面的L的内容不就是main()里L地址么,那么,*L不就是main里L的内容么,也就是说,对*L操作就是对main()里的L进行操作。


实战教程:如何用Python+小波变换+CNN搞定医学影像中的条纹噪声(附完整代码) 本文提供了一套完整的实战方案,指导如何利用Python结合小波变换与卷积神经网络(CNN)去除医学影像中的条纹噪声。该方法通过小波变换精准定位噪声,再使用轻量化CNN进行针对性清除,有效保护图像细节,并附有可运行的完整代码,为医学影像处理与AI分析提供高效工具。 阅读详情

相关推荐

livebos报表开发

文章目录1.参数的设定2.展示的内容3.综合展示的效果4.调用过程5.可以在数据库里面查看6.注意事项7.过程代码 1.参数的设定 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-flb5C49A-1619516341977)(/uploads/xinxibuneibuzhishiku/images/m_bc71bb4608053778dbf29e06cd102ae1_r.png)] 2.展示的内容 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-

阿浪的专栏 709

C语言参数传递(值传递、地址传递)+二级指针

参数传递 C语言参数传递一般分为:值传递和地址传递(本质上只有值传递) (注意:C语言中没有引用传递,C++才有引用传递,因为很多C语言环境是用C++编译器编译,使得C看起来支持引用传递,导致很多网上很多blog都把引用传递归为C语言参数传递的一类, 当使用Microsoft Visual C++ 2010 Express或VC6之类的编译器时使用引用传递就无法编译通过) 值传...

weixin_30326515的博客 885

FPGA设计中的扇出约束实战:从XDC到代码优化的全流程解析

本文全面解析FPGA设计中扇出约束的重要性与应用,详细介绍了从XDC约束文件设置到HDL代码优化的全流程实战技巧。通过MAX_FANOUT约束控制信号负载,结合寄存器复制和物理优化策略,有效解决高扇出导致的时序违例和布线拥塞问题,提升设计性能和可靠性。

nept的博客 797

C语言函数传递指针参数的问题(包含传递双指针)

https://blog.youkuaiyun.com/gl486546/article/details/53375999

Young_Fan 3231

Reeds-Shepp曲线公式推导及代码实现-第二部分(共三部分)

文章目录2. Reeds-Shepp求解2.1 L+S+L+L^+S^+L^+L+S+L+2.2 L+S+R+L^+S^+R^+L+S+R+2.3 L+R−L+L^+R^-L^+L+R−L+2.4 L+R−L−L^+R^-L^-L+R−L−2.5 L+R+L−L^+R^+L^-L+R+L−2.6 L+Rβ+Lβ−R−L^+R_{\beta}^+L_{\beta}^-R^-L+Rβ+​Lβ−​R−2.7 L+Rβ−Lβ−R+L^+R_{\beta}^-L_{\beta}^-R^+L+Rβ−​Lβ−​R+2.8

jianmo的博客 1212

Sonatype nexus3 数据迁移及升级3.71+(迁移到H2数据库)

nexus3旧版本OrientDB升级H2,及整体迁移nexus3数据到其它服务器。

葫芦娃 5554

C语言函数传递指针时的问题

函数传递指针变量时,在函数体中可以通过访问传递过来的指针地址修改指针的内容。但是如果在函数体中定义一个同名的指针并修改他的内容是无法对原指针造成影响的。 例如: #include <stdio.h> void f (int* a); int main () { int p, t; int *a, *b; p = 1; t = 2; a = &p; b = &amp...

Math Love Computer 981

Xilinx FPGA 10G Ethernet Subsystem example

The 10G Ethernet subsystem provides 10 Gb/s Ethernet MAC, Physical Coding Sublayer(PCS) and Physical Medium Attachment (PMA) transmit and receive functionality over anAXI4-Stream interface.

青城扬沙的博客 2380

javascriptES5 中 filter()选择方法

filter() array.filter(function(currentValue, index, arr)) filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素,主要用于筛选数组 注意它直接返回一个新数组 currentValue: 数组当前项的值 index:数组当前项的索引 arr:数组对象本身 <script> var arr=[50,86,12,10,0,38,12]; var arr1=[];

weixin_44638167的博客 1637

超详细教程YoloV8官方推荐免费数据集网站Roboflow一键导出Voc、COCO、Yolo、Csv等格式

YoloV8官方推荐了一个数据集网站,就是Roboflow。Roboflow是一个数据集管理平台,提供了免费的数据集,同时也支持上传自己的数据集进行格式转换。使用Roboflow,开发者可以方便地获取所需格式的数据集,无需手动转换格式。此外,Roboflow还提供了多种数据预处理、数据增强等功能,可帮助开发者更好地优化训练数据

Snu77的博客 2万+

【AI for Medecine】吴恩达医学图像AI专项课程(诊断、预测、治疗)

近期需要简单了解AI4Science上的一些应用,看到吴恩达大佬的专项课程,于是开始来个“全面”的了解--医学人工智能(诊断、预测、治疗)。

图挖掘领域,新晋砖家 ☞ 未来可期,欢迎和静静一起学习交流吖 772

c语言函数用指针传递参数问题

c语言函数用指针传递参数问题 问题1:你是把变量传给了函数,还是把地址传给了函数? 例: #include #include #include void oxx(char* dest) { dest = (char*)malloc

diligentcat的专栏 1783

2026年03月CCF-GESP编程能力等级认证Scratch图形化编程一级真题解析

本文收录于《,订阅后可阅读专栏内所有文章。

人生就是一个不断学习的过程 238

shell 函数传递参数_c语言 函数 用指针传递参数 问题

问题1:你是把变量传给了函数,还是把地址传给了函数?例: #include <stdio.h> #include <stdlib.h> #include <string.h> void oxx(char* dest) { dest = (char*)malloc(30); strcpy...

weixin_39621794的博客 185

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

C语言函数的参数传递问题(一)-----指针作为参数传递

我们用取地址运算符&,获取变量 a 和 b 的首地址,并将它们作为参数传递给 swap 函数。在 swap 函数内,我们声明了两个指针变量 x 和 y,并分别将 a 和 b 的首地址赋值给它们,此时指针x指向变量a的位置,指针y指向变量b的位置。按值传递意味着函数接收的是变量的副本,对副本的修改不会影响原始变量。通过指针使得被调函数间接地修改主调函数中的。函数时,需要对变量先取地址再传入参数了。会从读取从键盘的输入,转换后存储到变量。实参与形参它们是相互独立的。无法直接修改在主调函数中。

2303_76295261的博客 1129

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

c语言函数的参数是指针,C语言函数传递指针参数的问题

这货写的真详细,并且通俗易懂。看到的有福气了0.0呵呵一个问题是,我们想用一个函数来对函数外的变量v进行操作,比如,我想在函数里稍微改变一下这个变量v的值,我们应该怎么做呢?又或者一个常见的例子,我想利用swap()函数交换两个变量a,b的值,我们应该怎么做呢(好吧,博主是觉得这个问题是足够的老土)。如果你真的理解【函数】这个工具的本质,我想你稍微仔细的思考一下,可能就不会来查看博主的这篇文章,对...

weixin_33800919的博客 392

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

c语言指针函数计算机,c语言函数用指针传递参数问题

问题1:你是把变量传给了函数,还是把地址传给了函数?例:#include#include#includevoidoxx(char* dest){dest = (char*)malloc(30);strcpy(dest, "content has been modied");}voidoxx2(char* dest){strcpy(dest, "content hat been modied");}...

weixin_42168830的博客 102

c语言 函数 用指针传递参数 问题

问题1:你是把变量传给了函数,还是把地址传给了函数? 例:  #include        stdio.h> #include        stdlib.h> #include        string.h> void oxx(char* dest) {         dest = (char*)malloc(30);         strcpy(des

清新空气的专栏 548

【学习笔记】C 语言中未开辟地址的指针作为函数参数传递的问题

先来看下面的一段程序,理论上我们期望的结果是 inner 和 outer 部分都输出 10,但实际运行的时候, 会报错 p 是一个 nullptr 不能输出,但是我们不是在 pointerSon 中对 p 指针开辟了空间吗,开辟了空间后也对它赋值了 10 啊,为什么没有得到期望的结果呢? 事实上,导致这个结果的原因是,在 中传递的参数并不是指针传递,而是值传递,值传递是实参的拷贝副本,所以当执行完 后, 里的 p 并没有改变,我们通过图画来阐述这个过程 【注】图中 0x123 和 0x456 为演示方

码的世界 782
上一篇: redis操作测试
下一篇: Java多线程(四)、线程池
TuxedoLinux
博客等级 码龄9年 268粉丝 34原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值