目录
【理解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,并不对原数据产生影响。
如果你想要详细理解函数在传参时的操作,可以看:
为什么有传址?
但实际上一些问题只通过传值是无法解决的,例如:
(交换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.在函数内部修改变量的值可能会产生想不到的结果,因此使用传址需要谨慎处理;
(可以定义常变量,常量来避免)
完
未经作者同意禁止转载