C语言 参数传递与作用域.ppt_第1页
C语言 参数传递与作用域.ppt_第2页
C语言 参数传递与作用域.ppt_第3页
C语言 参数传递与作用域.ppt_第4页
C语言 参数传递与作用域.ppt_第5页
已阅读5页,还剩41页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、参数传递与作用域,函数调用过程,函数调用离不开栈。栈是一种数据结构,具有先进后出的特点,也就是说最先进入栈的数据总是最后从栈里出来。 函数调用时,需要处理初始化和善后的工作,这些都是在栈空间里完成的。函数调用按照以下步骤进行。,在栈里保存函数调用现场和函数返回地址,以便当函数调用完毕后,能返回主调函数,并且能让程序继续往下执行。 在栈里给形参分配空间。 计算实参表达式的值,然后将这个值拷贝给形参。 执行函数体。 函数体执行完毕后,通过弹栈操作释放形参所占的空间,并且得到返回地址和调用函数的现场状态,返回主调函数。,【例12-1】: #include using namespace std;in

2、t GetMax(int a,int b)if(ab) return a;else return b; void main() int a = 10; int b = 20; int c = GetMax(a,b); /调用函数,将实参的值拷贝给形参变量 couta“和”b“中较大的数是:” cendl; ,函数调用时的内存状态如图,函数调用方式,函数调用的一般形式: 函数名 (实参表) 若被调用的函数的没有参数,则实参表为空。 通常可以采用下面的方式来调用函数:,调用函数完成一定的功能,而不需要函数返回结果。若函数调用带有返回值,则这个值将会自动丢弃。例如: DisplayMsg(How a

3、re you); GetMax(9,4); /调用GetMax函数,但并没有使用函数的返回值,这个返回值会自动丢弃,2、另一种方式是调用函数,执行一定的操作,得到函数的返回值,并且把这个返回值代入表达式中参与计算。例如: int a = GetMax(9,4); int a = GetMax(9,4) + 1; cout GetMax(9,4)endl; if(GetMax(9,-4) 0) cout“最大值小于零。endl; int a=9; a=GetMax(GetMax(a,6),4);,函数(原型)声明,函数如果在定义之前使用必须先进行声明,即告诉系统该函数定义将在程序的后面部分定义。

4、 函数的声明形式为: 返回类型 函数名(形参及其类型表); 就算调用库函数,也必须声明。通常在本文件的开头用#include命令将调用有关库函数时所需用到的信息包含到本文件来。 对函数原型的说明,通常放在程序的顶部,也可以存放到一个头文件中,然后利用#include语句嵌入到程序中。,函数原型声明,函数必须先定义后调用,如果自定义函数在主调函数的后面,就需要在函数调用前,加上函数原型声明。 如果函数的定义在函数调用之前,可以不用函数声明 函数声明:说明函数的类型和参数的情况,以保证程序编译时能判断对该函数的调用是否正确。,只写函数定义中的第1行(函数首部),并以分号结束。,【例12-2:】函数

5、声明(求一个数的n次方) #include using namespace std; int Power (int base,unsigned int exponent); void main (void)cout 2 8 = “ Power(2,8) n; int Power (int base,unsigned int exponent)int result = 1;for (int i = 0; i exponent; +i) result *= base; return result;,参数传递,在前面已经提到,函数进行参数传递,是在栈空间里为形参分配空间,并将计算各个实参的表达式的值

6、,然后一一拷贝给形参的过程。 根据函数的参数传递的不同,函数调用可以分为函数的值传递调用(传值调用)、函数的指针传递调用(传址调用)和函数的引用传递调用。,函数的值传递调用,传值调用将函数的实参表达式的值拷贝给形参。这样,实参变量和形参变量占据的是不同的存储空间,因此在函数里对形参变量的改变不会影响到实参变量的值。当函数返回时,由于对栈的操作,形参所占据的存储空间就被系统收回了,也就是说形参变量的值消失了。 这样做的好处是:通过这样的方式将形参和实参隔离,使函数与函数之间的关联减到最低,有利于实现模块化的设计,同时我们也不需要为要不要在调用函数之前保存实参的值而操心。如下例:,#include

7、 using namespace std; void func(int a,int b); /函数声明 void main() int a = 10; int b = 20; func(a,b); couta=a ,b=bendl; void func(int a,int b) a = 30; b = 40; couta=a ,b=bendl;,#include using namespace std; void Swap(int a,int b); void main() int a= 10; int b = 20; cout“交换前a=a,b=bendl; Swap(a,b); cout交

8、换后a=a,b=bendl; void Swap(int a,int b) int nTmp; nTmp = b; b = a; a = nTmp; ,按照上面写法,Swap函数里的形参a、b和main函数里的变量a、b存储空间不同,在Swap函数里修改了变量a、b的值,并不能影响到main函数里的变量a、b,所以达不到在Swap函数里交换两个变量的值的目的。为了达到目的,我们需要将函数的参数传递方式改变为指针转递方式,如下:,函数的指针传递调用,在以下情况,使用函数的值传递调用方式不太恰当或者不能达到目的: 要传递的参数是一个比较大的自定义的复杂数据类型,如果按值转递方式,需要将这个复杂的数

9、据类型在被调用的函数的栈空间复制一份,这样对时间和空间的开销都比较大。 有时需要在被调用函数里改变实参变量的值。 这时,可以使用函数的指针传递调用的方式来传递参数。,其方法是将函数的形参声明为指针,然后在函数调用时,将实参的地址传递给形参。在参数传递时,是将实参的地址复制给形参。 在被调函数里,对形参指向的内存空间进行操作,实际上就是对主调函数里的实参变量进行操作。因为函数的指针传递调用传递的是地址,所以函数的指针传递调用又称为传址调用。 请大家思考,如果要定义一个交换两个变量的值的函数,应该怎么写?,void Swap(int *pa,int *pb); void main() int a=

10、 10; int b = 20; cout交换前a=a,b=bendl; /下面的语句将变量的地址作为实参传递给形参,从而使形参指向了main函数里的变量a、b Swap( ,函数的返回值只能带回一个结果,如果程序需要函数返回多个值,应该怎么办呢?实际上,上面的Swap函数可以看作是返回了两个值。所以解决这个问题的方法之一就是用指针来传递函数的参数。通过指针来改变主调函数里的变量的值,实际上就是向主调函数返回了多个值。,函数的引用传递调用,函数也可以通过引用来传递参数。使用引用传递参数与传递指针的效果一样。如果将形参定义为引用,那么当进行参数传递时,实际上是将形参与实参绑定起来,让形参成为实参

11、的别名,而并不是将实参拷贝了一份给形参。因为形参是实参的别名,所以对形参的操作等同于对实参变量的操作。 下面用引用传递的方式来修改Swap函数。,#include using namespace std; void Swap(int ,void Swap(int ,变量的作用域(空间特性),+语言中的变量,定义位置不同,其作用域也不同,据此将变量分为内部变量和外部变量。 变量的作用域也称为可见性,按变量能够被访问的范围分为局部变量和全局变量两类:局部变量的范围较窄,限定在程序中的部分区域;全局变量的范围较宽,可以是整个文件甚至是整个程序。,定义:在函数内或复合语句内定义,只在本函数内或复合语句

12、内有效 说明: main中定义的变量只在main中有效 不同函数中同名变量,占不同内存单元 形参属于局部变量 可定义在复合语句中有效的变量,局部变量(内部变量),局部变量的作用范围(作用域):只局限在定义它的本函数体之内。 局部变量的生存期(存在的时间):只有当程序执行到本函数时,才给这些局部变量分配存储单元,当本函数执行完毕后,这些局部变量所占存储单元就被释放。,void sub() int a,b; a = 6; b = 7; coutsub:a=a,b=bendl; void main() int a,b; a = 3; b = 4; coutmain:a=a,b=bendl; sub(

13、); coutmain:a=a,b=bendl; ,#define N 5 void main() int i; int aN = 1,2,3,4,5; for(i=0;iN/2;i+) int temp; temp = ai; ai = aN-i-1; aN-i-1 = temp; for(i = 0;i N;i+) coutai; ,例 不同函数中同名变量,例 复合语句中变量,运行结果:5 4 3 2 1,运行结果: main:a=3,b=4 sub:a=6,b=7 main:a=3,b=4,静态局部变量,定义方法是:在函数体内定义变量采用: static 类型标识符 变量名; 特点: 静

14、态局部变量本身也是局部变量,因此其作用域也是局限在定义它的本函数体内,当离开本函数体,该变量就不再起作用,但其值还继续保留。 另一方面,静态局部变量又是静态存储类别的变量,所以,在整个程序运行开始就被分配固定的存储单元(占用静态存储区),整个程序运行期间不再被重新分配,所以其生存期是整个程序运行期间。,静态局部变量的赋初值的时间在编译阶段,并不是每发生一次函数调用就赋一次初值。当再次调用该函数时,静态局部变量保留上次调用函数时的值。,【例12-3:】 #include using namespace std; int count(); void main() for (int i=0;i=9;

15、i+) coutcount()endl; int count() static int iCount; return +iCount; ,void main() int i; for(i=0;i 3;i+) inc1(); for(i=0;i 3;i+) inc2(); ,例 静态内部变量的生存期,void inc1() int x=0; x+; coutin inc1 x=“x; void inc2() static int x=0; x+; coutin inc2“x); ,运行结果: in inc1 x=1 in inc1 x=1 in inc1 x=1 in inc2 x=1 in i

16、nc2 x=2 in inc2 x=3,全局变量,在所有函数体外部定义的变量为外部变量(全局变量),全局变量可以被本文件中其他函数所调用(使用)。 全局变量的有效范围为:从定义该变量的位置开始到本程序文件的结束。 说明: 全局变量在程序的全部执行过程中都占用固定的内存储单元,而不是仅在需要时才开辟单元,所以其生存期是整个程序运行期间。,全局变量处于文件的开头定义时,其作用范围为整个文件。 同一项目下,若要在一个源文件里使用其他源文件中定义的全局变量,需要在源文件中使用extern说明。 说明的格式是: extern 类型标识符 变量名; 在同一个文件中全局变量与局部变量同名时,则在局部变量的作

17、用范围内,全局变量不起作用。,【例12-4:】 #include int count(); int iCount; void main() for (int i=0;i=9;i+) coutcount()endl; int count() return +iCount; ,【例12-5:】 /f0.cpp #include int Max,Min; void func(int x,int y); void main() int a,b; cinab; func(a,b); coutMax=Maxendl; coutMin=Minendl; ,/f1.cpp void func(int x,in

18、t y) extern int Max,Min; Max=(xy)?x:y; Min=(xy)?x:y; ,注意,! 应尽量少使用全局变量,因为: 全局变量在程序全部执行过程中占用存储单元 降低了函数的通用性、可靠性,可移植性 降低程序清晰性,容易出错,int a = 3, b = 5; int max(int a, int b) int c; c=ab?a:b; return(c); void main() int a = 8; coutmax(a,b); ,例 外部变量与局部变量(同名的局部变量屏蔽外部变量),运行结果:8,int add(int x,int y) int z; z=x+y

19、; return z; void main() extern int a,b; coutadd(a,b); int a=3, b=4;,例 用extern扩展外部变量作用域,运行结果: 7,例 用extern将变量的作用域扩展到其它文件中,int x=10,y=10; extern void sub(); void add() int y =5; y = 10+x; x *= 2; coutadd:y=:“y; void main() x+=5; add(); sub(); coutmain:x=“x“main:y= “y; ,extern int x; void sub() int y=5;

20、 x -= y; coutsub:y=“y; ,file1.c,file2.c,运行结果: add:y=25;sub:y=5; main:x=25;main:y=10;,static int x=10; void add2() extern int y; x+=10; y+=2; coutin add2 x=“x; ,例 static 型外部变量的作用域受到限制,限制在本文件内使用,运行结果: in add1 x=4 in add2 x=20 in add1 x=6 in add2 x=30 x=6;y=13,static int x=2; int y=3; extern void add2(); void add1(); void main()

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论