C语言函数的参数会出现在两个地方,分别是函数定义 (函数实现)处和函数调用处。形参和实参的功能是传递数据,发生函数调用时,实参的值会传递给形参。
形参(形式参数)
在函数定义(函数实现)中出现的参数可以看做是一个占位符,它没有数据,只能等到函数被调用时接收传递进来的数据。可以理解为形参是重新申请了一块新的空间,然后把实参的值复制粘贴进去(当然形参的类型要和实参相同),所以形参的改变并不会导致实参的改变。
实参(实际参数)
函数被调用时给出的参数包含了实实在在的数据,会被函数传递给形参。 实参可以是常量、变量、指针、表达式、函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值(当我们传一个int类型的变量a时,我们实参接受到的并不是一个变量,而是变量当前所属的确定的一个值。同理我们比较难理解的传递指针变量,实际上形参接收到的也是一个确定的地址)所以应该提前用赋值、输入、运算等办法使实参获得确定值。
void Alter(int a,int b)//这里也可以用int c,int x或其他变量来接收,只要类型上一致就行
//这里我们也可以理解为是创建了int a变量然后把实参传递过来的值
//赋给变量a;它与实参是属于两块不同的内存空间
{
a = a+2;
b = b+3;
}
int main()
{
int a,b;
a = 1;
b = 2;
Alter(a,b);
printf("a = %d b = %d",a,b)//打印出的结果是a = 1 b = 2
//虽然函数是对a,b变量进行了更改,
//但因为实参和形参是两块不同内存
//所以形参的改变并不会导实际参数发生改变
return 0;
如果形参只是实参的复制,那如果我们要用函数对我们的数据进行更改加工,我们应该怎么操作呢?
主要有两种方法,第一种方法是接收返回值,第二种是传递指针,然后对指针解引用来改变指针所指向的数据
int Sub(int a,int b)
{
int c = a+b;
return c;
}
int main()
{
int a,b,c;
a = 2;
b = 3;
c = Sub(a,b);
printf("%d",c);//这里输出的值是 5
return 0;
}
【精选】【详解】函数栈帧——多图(c语言)_函数帧-CSDN博客
这里给大家推荐另外一个博主的文章,因为我们函数中的参数是存放在栈区中,函数返回值是唯一会在出栈时被保留的数据,因为返回值的数据是放在寄存器中的,可以被我们引用。
第二种方式就是我们c语言中最常用的,也是我们觉得的c语言中的难点的传递指针,通过对指针的解引用来改变数据
void Sub(int *a,int *b)
{
*a = 5;
*b = 8;
}
int main()
{
int a,b;
a = 2;
b = 3;
Sub(&a,&b);
printf("a = %d b = %d",a,b);//这里输出的是 a = 5 b = 8
return 0;
}
不管是传递指针还是传递其他数据,本质还是一样的,实参数传一个确定的值,形参是创建一个变量来接收(复制粘贴)实参的值。
可以把指针理解为一个房间的钥匙,而指针所指向的内存数据,相当于一个房间,函数传参的时候相当于,实参让形参去复制了一把一模一样的钥匙b,钥匙b和原来的钥匙(钥匙a)都可以开指定房间的门 ,但当我们对钥匙b进行修改的时候,并不会导致钥匙a的改变,但是我们用b钥匙去打开房间,然后对房间内的数据进行改变。
void Sub(int *a)
{
int c = 5;
a = &c;
}
int main()
{
int a;
a = 2;
Sub(&a);
printf("a = %d",a);//这里输出的结果是a = 2
return 0;
}
由上面这个代码可知,我们通过函数传参的方式,可以改变的是指针所指向的对象,但改变我们传递的指针是无效的。因为不管是是常量,变量,指针,表达式,函数,我们传的都是形参数,形参和实参是分别占用两块不同的内存空间,对形参的修改并不会导致实参的改变
1) 形参变量只有在函数被调用时才会分配内存,调用结束后,立刻释放内存,所以形参变量只有在函数内部有效,不能在函数外部使用。
2) 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参,所以应该提前用赋值、输入等办法使实参获得确定值。
3) 实参和形参在数量上、类型上、顺序上必须严格一致,否则会发生“类型不匹配”的错误。当然,如果能够进行自动类型转换,或者进行了强制类型转换,那么实参类型也可以不同于形参类型。
4) 函数调用中发生的数据传递是单向的,只能把实参的值传递给形参,而不能把形参的值反向地传递给实参;换句话说,一旦完成数据的传递,实参和形参就再也没有瓜葛了,所以,在函数调用过程中,形参的值发生改变并不会影响实参。