如果被调函数的形式参数是指针型参数,则主调函数中对应的实际参数就必须是同类型指针值(地址量),这种函数调用参数传递的方式称为传地址值方式。地址值参数传递函数调用示例。在例5.6的程序中,函数调用时将实参a和b的值复制给函数summul的形式参数x和y,实参变量mul将自己的地址传递给指针形式参数v。......
2023-11-20
程序的执行过程中,一个函数调用另外一个函数以完成某一特定的功能称为函数调用。调用者称为主调函数,被调者称为被调函数。C程序中,函数调用可以是表达式中的一部分,也可以由函数调用构成一条单独的C语句。函数调用时只需要提供被调函数的名字和需要提供给它的数据(实际参数),函数调用的一般形式为:
函数名(实际参数表)
其中,函数名指定了被调用的对象;实际参数表(简称为:实参表)确定了主调函数传递给被调函数的数据信息。
C程序中对函数的调用方式有3种:
·函数语句方式。函数调用作为一个单独的C语句出现,此种方式主要对应于返回值为空类型(void)函数的调用。对返回值类型为非void的函数,采用函数语句方式调用表示程序中对函数的返回值不予使用(放弃),如常用的printf和scanf函数调用。
·函数表达式方式。如果函数调用出现在一个表达式中,该表达式亦称为函数表达式。此时要求函数调用结束后必须返回一个确定的值到函数调用点以参加表达式的下一步运算。显然,返回值类型为void的函数不能使用该方式调用。
·函数参数方式。函数调用作为另外一个函数调用的实际参数出现,此时要求函数被调用后必须要返回一个确定的值以作为其外层函数调用的实际参数。同样,返回值类型为void的函数不能使用该方式调用。
C程序执行过程中,函数调用主要由下面4个步骤组成:
①创建形式参数和局部变量。被调函数有形式参数时,系统首先为这些形式参数变量分配存储(创建它们),同时创建函数内部用到的局部变量。
②参数传递。如果是有参函数调用,主调函数将实际参数传递给被调函数的形式参数,传递时要求实参和形参一一对应,即参数的个数、类型、次序都要正确。
③执行被调函数。参数传递完成后,程序执行的控制权转移到被调函数内部的第一条执行语句,执行被调函数的函数体。
④返回主调函数。当执行到被调函数中的return语句或者被调函数体的右花括号“}”时,将被调函数的执行结果(返回值)以及程序执行流程返回主调函数中的函数调用点。若被调函数没有返回值,则只将执行流程返回主调函数。
函数调用时,实参的值传递到形式参数中就实现了数据由主调函数到被调函数的传递。在函数间使用参数传递数据的方式有两种:传递数值方式和传递地址值方式。
函数的传递数值调用方式是一种数据复制的方式。函数调用时,实际参数值复制给形式参数,传递方(主调函数)中的原始数据和接受方(被调函数)中的数据复制品各自占用内存中不同的存储单元,当数据传递过程结束后,它们是互不相干的。因此在被调函数的执行过程中,无论形式参数变量值发生何种变化,都不会影响该形参所对应主调函数中的实际参数值。下面参照例5.3的程序讨论函数调用的执行过程,为了讨论方便为程序加上行号。
【例5.3】 传数据值方式函数调用示例。(www.chuimin.cn)
程序执行时,函数在被调用之前其形式参数表中的形式参数变量和函数体中定义的普通变量在系统中都是不存在的,它们在系统中出现或消失与函数调用的过程有着密切的关系,在例5.3程序执行到第8行之前,函数swap中的形参变量x和y以及函数体中定义的变量t在系统中均不存在,参见图5.2(a)。函数swap传数据值调用的过程如下:
①系统为被调函数中的局部变量分配存储。如在例5.3程序中,程序执行到第8行时系统才会创建swap函数中的变量x、y和t(即为这些变量分配存储),参见图5.2(b)。
②参数传递。传递参数值实质上是将实参变量的内容拷贝给形式参数变量,一旦复制完成则实际参数与形式参数就没有任何关系。在例5.3程序中,传递参数时将实参变量a的值复制给形参变量x,将实参变量b的值拷贝给形参变量y,复制完成后实参变量a、b与形参变量x、y就断开联系,参见图5.2(c)。
图5.2 swap函数值传递调用时参数的变化情况
③控制流程转移到被调函数执行。在例5.3程序中,参数传递完成后程序的控制流程(执行顺序)就从第8行转移到第14行开始执行函数swap,参见图5.2(d)(e)(f)。
④控制流程返回主调函数。程序控制流程执行到被调函数中的return语句或函数体的右花括号“}”时,将程序执行的控制流程以及被调函数的执行结果返回到主调函数中的调用点。若被调函数的返回值数据类型为void则没有返回值,只需要将控制流程返回到主调函数中的调用点即可。特别需要注意的是,随着程序控制流程的返回,系统会自动收回为被调函数形式参数和局部变量分配的存储单元,即在函数被调用时创建的形式参数和局部变量会自动撤销。在例5.3的程序中,程序执行到第19行时将控制流程返回到第8行的函数调用点后。与此同时,调用swap函数时创建的变量x、y和t都自动被系统撤销。
从上面的分析可以得到,虽然在swap函数内部对变量x、y的值进行了交换,但这种交换对函数调用时的实际参数变量a和b没有任何影响。程序执行的结果如下:
swap调用前:a=3,b=5
swap调用中:x=5,y=3
swap调用后:a=3,b=5
传值方式调用时,函数只有一个数据入口,就是实参传值给形参,也最多允许一个数据出口,就是函数返回值。这种调用方式使得函数受外界影响减小到最小程度,从而保证了函数的独立性。在设计传值调用函数时,函数的形式参数是普通变量。调用时的实际参数可以是同类型的常量、一般变量、数组元素或表达式。
有关C语言程序设计基础(第3版)的文章
如果被调函数的形式参数是指针型参数,则主调函数中对应的实际参数就必须是同类型指针值(地址量),这种函数调用参数传递的方式称为传地址值方式。地址值参数传递函数调用示例。在例5.6的程序中,函数调用时将实参a和b的值复制给函数summul的形式参数x和y,实参变量mul将自己的地址传递给指针形式参数v。......
2023-11-20
图5.3程序运行结果说明:定义函数时指定的形参变量在未出现函数调用时,并不占用内存的存储单元。图5.4程序运行结果说明:程序中实参与形参同名,但两者的作用范围不同,程序开始执行时,为主函数中的变量n分配存储空间,实参n 在主函数main()中有效;主函数调用函数s(),有效的是形参n。程序的运行结果表明,当函数调用时,实参的值传送给形参,在被调函数内部,形参的变化不会影响实参的值。......
2023-10-21
我们通过下面的示例来说明按值传递方式中参数在函数之间的传递。图5.1实参与形参传递示意图当数组名作为函数参数时,函数传递数据方式采用的是“按地址传递”的方式,但要求形参和相对应的实参都必须是类型相同的数组。图5.3数组v的存储形式这样一来,形参数组中元素值的改变就会反过来影响到实参数组。......
2023-11-18
在C语言中,以函数首部声明函数的形式称为函数原型。使用函数原型是C语言的一个重要特征,主要作用是利用它在程序的编译阶段对调用函数的合法性进行全面检查。......
2023-11-18
指针变量既可以作为函数的形参,也可以作为函数的实参。所以,为了解决通过被调用函数来实现主调函数中变量值的改变,必须使用指针变量作为函数的形参。在执行被调用函数时,使形参指针变量所指向的变量的值发生变化。函数调用完成后,通过不变的实参指针变量将变化的值保留下来。图6.8程序运行结果说明:函数swap 的形参是两个整型指针变量p1 和p2,故主函数在调用时,必须使用变量a 和b 的地址,即&a 和&b 作为实参。......
2023-10-21
在C 语言程序中,是通过对函数的调用来执行函数体,其过程与子程序调用相似。在调用函数时,大多数情况下主调函数和被调函数之间有数据传递。图5.2程序运行结果函数调用在程序中起一个表达式或者语句的作用。在调用函数时,有3 种不同的方式。这就要求该函数必须是有返回值的。getchar 函数调用作为表达式使用,即赋值表达式的右操作。......
2023-10-21
将一维数组看成一个整体作为函数参数时,用数组名作为函数的形式参数或实际参数。一维数组作为函数的形式参数本质上是一个指针变量,所以在描述上不需要指定形参数组的长度。上面程序中函数sum的原型为:int sum;,表示了该函数在被调用时应该传递一个整型数组给一维数组形式参数v[],数组的长度由整型变量n表示,函数sum的功能是将用形式参数v表示的长度为n的数组元素求和。......
2023-11-20
相关推荐