【理解C语言】为什么要区分传址与传值?

 

目录

什么是传值?

 为什么有传址?

怎么选择传值与传址?

 实例:

传值的优缺点:

传址的优缺点: 


        【理解C语言】栏目主要用来分享水墨对C的一些浅薄理解,在这里你可能会因看到一些困扰你很久的问题的解决思路,从而获得灵感。


什么是传值?

         我们先看一段代码:

e.g.1


#include<stdio.h>

int Add(int x, int y)
{
	int z = 0;

	z = x + y;

	return z;

}


int main()
{
	int a = 10;
	int b = 20;
	int c = 0;

	c = Add(a, b);

	printf("%d ", c);

	return 0;
}

        对于这段代码,我们很容易发现——函数Add只需得到a与b的值,然后相加再返回即可,不需要对a与b本身进行修改操作。

        传值是指数据传递给函数的形参时,实际传递的是数据的copy而不是数据本身。在传值过程中,变量本身的值不会被修改,只是将数据的值复制一份传递给函数的形参,也就是只对数据进行运算,不改变数据。

         就如e.g.1,我们在函数内部对数据进行求和,并不改变  形参  或  实参  的值。(而实际上改变形参对实参并没有影响)

        为什么呢?——>  改变原数据的一份copy,并不对原数据产生影响。

        如果你想要详细理解函数在传参时的操作,可以看:

【C语言】函数栈帧空间的创建与销毁-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/2301_79465388/article/details/134256464?spm=1001.2014.3001.5501

 为什么有传址?

但实际上一些问题只通过传值是无法解决的,例如:

 

 (交换a与b的值)

         为什么呢?

        当我们按F10开始调试,打开监视:

         我们发现:a与x的地址,b与y的地址,是不同的。(其实很容易理解:因为x是a的拷贝,y是b的拷贝)

        怎么解决这一问题,从而实现a与b的交换呢?

        这时,考虑将a与b的地址传入函数swap():

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

void swap(int* pa,int* pb)
{
	int tem = *pa;
	*pa = *pb;
	*pb = tem;
}

int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);

	printf("%d %d\n", a, b);

	swap(&a, &b);
		
	printf("%d %d\n", a, b);
	return 0;

}

        这样,就可以实现a与b的交换了:

怎么选择传值与传址?

         其实传址相对于传址好像更特殊,因为它让函数的形参与实参建立了真正的联系,可以在被调用函数中改变主调函数的变量的值,也就是说:

        如果函数中只是需要主调函数的变量的值 来实现计算 ,就可以采用传值调用。

        如果函数内部要修改主调函数中的变量的值,就需要传址调用。

 实例:

e.g.2

        当我们想要解决生活中的问题的时候,我们会编写一个程序,但是为了程序的可读性与整洁型,我们往往建立函数,为函数传递参数:

        其实不仅是解决数学问题,我们自己的一些行为也是函数的传值调用的过程!

        打一个有趣的比方:

        当你拿到数学试题,你不就是一个  “函数”  吗?你从试卷上接受信息,你写下的演算过程,甚至包括你得出的最终答案,不都是根据试卷(实参)的值,来把形参的最终值(形参)返回给阅卷老师(主调函数)吗?

e.g.3

当我们实现对数组的传参的时候,我们的需求大致有两种情况:

        1.不改变数组的值,完成函数的调用;

        2.在完成函数调用的同时,改变数组的值;

但是相信你已经知道,数组传参是传址的。

        在这种情况下,有什么技巧呢?

        第一种情况:

        例如:求数组的长度并返回长度的值,我们可以用const修饰不想要改变的数组名:


#include<stdio.h>

char* my_strcpy(char* p1, const char* p2)
{
	char* s = p1;
	while (*p1++ = *p2++)
	{
		;
	}
	return s;
}


int main()
{
	char str1[20] = "xxxxxxxxxxxxxx";
	char str2[] = "hello";

	char* p = my_strcpy(str1, str2);

	printf("%s\n", p);


	return 0;
}

         代码分析:这段代码模拟实现strcpy函数;

        while语句是一种非常巧妙地写法,一个语句就实现了:

        赋值,自增,判断多个功能。

        (这也正体现了C语言的紧凑严密的风格)


 

        第二种情况:

        也就是正常的得到数组的地址并进行操作的,例如:

        对一个数组进行操作,改变它的元素的值:

        

void initBoard(char Board[ROWS][COLS], int rows, int cols, char set)
{
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			Board[i][j] = set;
		}
	}
}

         代码分析:这段代码对二维数组进行初始化,比较容易理解。


传值的优缺点:

优点:

        1.防止意外修改数据,传值的方式可以确保调用者和被调用者使用的是不同的内存空间。

缺点:

        1.内存开销大:传值需要将整个实参的值复制到形参中

        2.效率较低:

        3.无法修改实参

传址的优缺点: 

优点:

        1.函数调用时传递的是地址,节省了内存空间;

        2.可以使函数修改调用它的上下文中的变量的值,更加方便;

缺点:

        1.在函数内部修改变量的值可能会产生想不到的结果,因此使用传址需要谨慎处理;

        (可以定义常变量,常量来避免)

       



未经作者同意禁止转载

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水墨不写bug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值