一、实参和形参的概念
实际参数(实参):
真实传给函数的参数,叫实参。 实参可以是:常量、变量、表达式、函数等。 无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
形式参数(形参):
形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。
二、一道关于实参和形参的例题
有这样一道例题,涉及到了函数实参形参的知识点内容,这道题是这样的:
写一个函数,使其能够 交换 两个的数
这道题我用了Swap1函数和Swap2函数来说明两种不同的传参方式
先来看看主函数:
int main()
{
int num1 = 1;
int num2 = 2;
Swap1(num1, num2);
printf("Swap1::num1 = %d num2 = %d\n", num1, num2);
Swap2(&num1, &num2);
printf("Swap2::num1 = %d num2 = %d\n", num1, num2);
return 0;
}
接着来看看Swap1函数:
void Swap1(int x, int y)
{
int tmp = 0;
tmp = x;
x = y;
y = tmp;
}
以及Swap2函数:
void Swap2(int *px, int *py)
{
int tmp = 0;
tmp = *px;
*px = *py;
*py = tmp;
}
不难看出,Swap1和Swap2的区别就是:
传给Swap1的是值,而Swap2是地址。这一点在函数的声明就可以看出,Swap1函数的参数是用int类型接收,而Swap2函数则是int*类型,是一个整型指针类型。
那么,这两种传值方式有什么区别呢?
来看下运行结果:
由此可见:Swap1函数不能完成我们的需求,而Swap2函数就能完成
但这其中的原因是什么呢,我这就来为大家揭秘
三、传值调用和传址调用
在解释上述现象之前,我们得先了解一下函数的传址调用和和传址调用的定义:
传值调用:
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
传址调用:
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
上面的定义,简洁点来说就是,一个传的是地址给函数,一个传的是值
像题中的Swap1函数就是传值调用,而Swap2函数则是传址调用
但这两种方式,在内存上有一个很关键的本质区别:
传值调用中,实参和形参指向的不是同一块内存空间,而传址调用中,我们则能够通过地址找到目标值,也就是这一点导致了运行结果的不同
下面是我在网课上看到的笔记:
Swap1 函数在调用的时候, x , y 拥有自己的空间(注意不是实参中 a 和 b 的那一块空间),同时拥有了和实参一模一样的内容。
所以我们可以简单的认为:形参实例化之后其实相当于实参的一份临时拷贝。
四、知识点总结
●实际参数 简称 实参,定义为 :真实传给函数的参数
●形式参数 简称 形参,是在函数名后括号中的变量。形式参数只有在函数被调用的过程中才实例化(分配内存单元)。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。
●传值调用:函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
●传址调用:传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。
●传值调用中,实参和形参指向的不是同一块内存空间,而传址调用中,能够通过地址找到目标值,也就是这一点导致了运行结果的不同。
●形参实例化之后其实相当于实参的一份临时拷贝。