形参:
在定义函数时指定的参数,在未出现函数调用时,他们并不占用内存中的存储单元。只有在发生函数调用时,函数中的形参才被分配内存单元,形参一般存在栈空间。在函数调用结束后,形参所占用的内存单元也被释放。
实参:
即你调用函数时传递的参数。实参可以是常量、变量、表达式。
形参和实参之间的传递
实参与形参的数据传递是“值传递”,单向传递,只能由实参传给形参,不能由形参传递给实参,形参的值如果发生改变,并不会改变主调函数的实参的值。
1、按值传递(实形无联系)
按传递就是平常编程中经常用到的,定义一个基本数据类型的变量,在调用某函数时把该变量作为函数的实参传递给函数。这种传递方式采用的是单向值传递,实形无联系,形参改变不影响实参。
2、按地址传递(通过操作形参可能会改变实参)
按地址传递主要出现在函数参数是指针变量、数组等的时候。
实质上用指针做函数参数的情况下,在调用函数时,将实参变量的传递给形参变量,采取的依然是单向值传递。如果在被调函数中只是单纯改变了形参指针变量的值,在函数调用结束后这些形参被销毁,是不会影响调用函数时传入实参指针变量值。
只有当你在被调函数中通过操作形参指针变量,去改变了指针指向变量的值时,才可以改变实参指针变量所指向变量的值。也只有这种情况下形参改变才可能影响实参。
关于按值传递和按地址传递的两种情况可看下例。
#include <stdio.h> int *a = NULL; int b = 1; void fun1(int q) { q++; printf("fun1形参q=%d\n",q); return; } void fun2(int *p) { (*p)++; printf("fun2形参*p=%d\n",*p); return; } void fun3(int *p) { p++; printf("fun3形参p=%d\n",(int)p); return; } int main(void) { //1.按值传递,形参改变,实参不变 printf("fun1调用前,实参b=%d\n",b); fun1(b); printf("fun1调用后,实参b=%d\n",b); //2.按值地址传递,形参改变影响实参的值 a = &b; printf("fun2调用前实参b=%d\n",b); fun2(a); printf("fun2调用后实参b=%d\n",b); //3.按地址传递,形参改变不影响实参的值 printf("fun3调用前实参a=%d\n",(int)a); fun3(a); printf("fun3调用后实参a=%d\n",(int)a); return 0; }
输出结果:
fun1调用前,实参b=1 fun1形参q=2 fun1调用后,实参b=1 fun2调用前实参b=1 fun2形参*p=2 fun2调用后实参b=2 fun3调用前实参a=6295608 fun3形参p=6295612 fun3调用后实参a=6295608