C语言程序设计第四章函数和作用域.ppt

上传人:xin****828 文档编号:19957001 上传时间:2021-01-18 格式:PPT 页数:49 大小:350.37KB
返回 下载 相关 举报
C语言程序设计第四章函数和作用域.ppt_第1页
第1页 / 共49页
C语言程序设计第四章函数和作用域.ppt_第2页
第2页 / 共49页
C语言程序设计第四章函数和作用域.ppt_第3页
第3页 / 共49页
点击查看更多>>
资源描述
第四章 函数和作用域 第四章 第一节 函数的定义和说明 第四章 一、 函数的定义格式 在 C+中一个 函数的定义格式 : () 函数的定义格式 的几点说明: 1、 、 、 构成了函数的函数 头。 2、用花括号 括起来的 组成了函数体 。函 数体内无论多少条语句,花括号是不可省的 。 第四章 3、 是该函数的类型 ,即为该 函数返回值的类 型 , 如果该函数没有返回值 , 只是一个过程调用 , 则 该函数的类型为 void , 在 C+程序中函数的类型不 可省略。 4、 是由 0个、 1个或多个参数组成 , 参数个 数为 0,表示没有参数 ,但是圆括号不可省 , 多个参 数之间应用逗号分隔 ; 每个参数包括参数类型和参 数名。 中的参数称为形式参数,简称形 参。 形参在该函数被调用时才被初始化的 。 形参的 使用将使被调用函数可以从调用函数那里获取数 据。如果被调用函数不需要从调用函数那里获取数 据 , 则该函数参数为空 。 第四章 二、 函数的说明方法 : 1、 说明调用函数的方法 : (); 函数 说明 又 称为原型说明 。 其格式同于定义函数 时的函数头 , 包括函数的类型、 函数 名和 函数参数的 个数及其 对应的类型 。原型说明 与 C语言中 的简单说明 是不 同的。 2、 在 C+中函数的说明原则 : 如果一个函数定义在先 , 调用在后 , 调用前可以 不必说明 ; 如果一个函数定义在后 , 调用在先 , 调用 前 则 必须说明 。 例 1、 使用原型说明的例子 第四章 #include void fun1(),fun2(),fun3(); void main() cout”It is in main.endl; fun2(); coutIt is back in main.endl; void fun1() coutIts in fun1.”endl; fun3(); cout”Its back in fun1.”endl; 第四章 void fun2() coutIts in fun2. endl; funl(); cout”Its back in fun2.end1; void fun3() coutIts in fun3.endl; 第四章 第二节 函数的调用 第四章 一、函 数的值和类型 : 一个函数被定义以后就是为了将来对它调用 , 函 数的调用是用一个表达式来表示的。 函数 调用格式 : () 、 可以是 0个、 1个或多个实在参数 ,如 果是 多个参数用逗号分隔 。 、 每个参数是一个表达式。 、 实参的个数由形参决定 , 实参是用来在调用函 数时给形参初始化的 ,因此 实参的个数和类型要 与形参的个数和类型一致 ,并且 初始化 时是 按其 位置对应进行 。 第四章 二、 函数的调用 : 1、 函数的传值调用 : 该调用同 C语言,分如下两种: ( 1)、传值调用: 传递变量本身值的 函数 调用 。 使用传值调用时, 调用函数的 实参用 常量 、 变量 值或 表达式 , 被调用函数 的 形参用变量名 , 实参将复 制副本形参。 传值调用的特点是在被调用函数中形参的改变将 不影响调用函数的实参。 例 2、一 个传值调用的例子。 第四章 #include void swap1(int x, int y) int temp; temp=x; x=y; /将 y值赋予了 x y=temp; /将 x的值赋予 y coutx=x,y=yendl; void main() int a(5),b(9); swap1(a,b); couta=a,b=bendl; 第四章 ( 2)、传址调用: 传递变量 地址 值的 函数 调用 。 使用传址调用方式时 ,调用函数的 实参用地址值 , 被 调用函数的 形参用指针 , 调用时将实参地址值传送 给形参指针, 即让指针指向实参变量或对象。 在被调 用函数中可以通过改变形参指针所指向的实参变量值 来间接改变实参值。 传址调用的特点是可以通过改变形参所指向的变 量值来影响实参。 例 3、 一个传址调用的例子。 第四章 #include void swap2(int *x,int *y) int temp; temp=*x; *x=*y; *y=temp; coutx=*x,y=*yendl; void main() int a(5),b(9); swap2( couta=a,b=bendl; 第四章 2、引用调用 : 引用调用是 C+中的一种函数调用方式 , C语言中 没有这种调用方式 。 引用调用时, 调用函数的 实参用变量名或对象 名, 被 调用函数 的 形参用变量或对象的引用 。而 实际 传送的是地址值 。 在被调用函数中改变形参值,则调 用函数中实参值也被改变。 引用调用具有传址调用的特点,而在操作中又比 传址调用方便、直观。 因此,在 C+程序中多用引用调 用。 例 4、 一个引用调用的例子 第四章 #include void swap3(int temp=x; x=y; y=temp; coutx=x,y=yendl; void main() int a(5),b(9); swap3(a,b); couta=a,b=bendl; 第四章 三、 函数的嵌套调用 : C+程序中允许函数的 嵌套调用 : 函数调用 是 逐级 调用,然后逐级返回的过程。 即 在调用 A函数的过程中 , 可以调用 B函数 ,在调用 B函数的过程中 ,还可以调用 C函 数 。当 C函数调用结束后 ,返回到 B函数 ,当 B函数调 用结束后 ,再返回到 A函数。 四、函数的递归调用: 递归调用: 是指在调用一个函数时,直接或间接 地调用该函数自身的过程。 直接递归调用: 是指在调用一个函数的过程中, 又调用了该函数。 第四章 间接递归调用: 是指在调用一个函数的过程中调 用了另一个函数,而在另一个函数中又调用了该函数。 1、 递归调用的特点及方法: ( 1)、特点: 使用递归调用方法编写的程序简洁清 晰,可读性强,但是程序在执行时占用的时间和空 间都比较大。 ( 2)、方法 :将原有问题能够分解为一个新问题 ,而 新问题又用到原有问题的解法 ,这就出现了递归。 实际中,有限的递归调用是有意义的,而无限的递 归调用是没有意义的。数学中求正整数阶乘的问题 就是典型的有限的递归调用的例子。 第四章 2、递归调用的过程: 具体可分为两个阶段: 第一个阶段称为 “ 递推” 阶段。这一阶段将原有 问 题不断地分解为新的子问题,逐渐从未知的向已知的 方向推测,最终到达已知的条件,即递归结束条件, 这时递推阶段结束。 第二个阶段称为 “回归” 阶段。此阶段是从已知 的 阶段出发,按照“递推”的逆过程,逐一求值回归, 最后 到达递推的开始处,结束回归阶段,完成递归调用。 如 求正整数阶乘的问题。 第四章 第三节 函数 参数及内联函数 第四章 一、函数参数的求值顺序: 当一个函数带有 多个 参数时 ,C+语言没有规定在 函数调用时实参的求值顺序 , 而编译器根据对代码进 行优化的需要自行规定对实参的求值顺序。 因此应 注 意 不同编译系统中,函数参数求值的顺序可能不同, 当实参表达式中出现有副作用的运算符时,可能产生 二义性。 二、设置函数参数的默认值: 在 C+语言中 ,允许在函数的 说明或定义时 给一个 或多个参数指定默认值。 具体 规则 如下: 第四章 (1)、设置参数默认值时,要求 从右向左设置 ,即 要求 在一个指定了默认值的参数的右边不能出现没有指 定默认值的参数。 (2)、 调用设置了默认参数的函数时,对应实参如果 没有,则用默认值,如果存在,则用实参值。 (3)、如果一个 函数有说明出现时, 设置参数默认值 应放在函数说明中。 例 5、 一个将参数默认值设置在函数的说明中的例子 第四章 #include int m(8); int add_ int (int x, int y=7,int z=m); void main() int a(5),b(15),c; int s=add_int(a,b,c); coutsendl; int add _ int ( int x, int y, int z) return x+y+z; 运行结果: 28 第四章 三、数组名可作为函数参数: 数组作函数参数可以分为三种情况 ,这三种情况所 采用的调用机制不同 ,但 是结果相同 。 1、 形参和实参都用数组 : 调用函数的 实参用数组名 ,被调用函数的 形参用数 组 ,这种调用的机制是形参和实参共用内存中的同一个 数组 。因此 ,在被调用函数中改变了数组中某个元素的 值 ,对调用函数该数组的该元素值也被改变 。 例 6: #include int a8=1,3,5,7,9,11,13; void fun(int b ,int n) for (int i=0;in-1;i+) 第四章 b7+=b i; void main() int m=8; fun (a, m); couta7endl; 运行后结果为 :49 2、 形参和实参都用对应数组的指针 : 在 C+中 ,数组名被规定为是一个指针 ,该指针便是 指向该数组的首元素的指针。 实际中 ,形参和实参一个 用指针 ,另一个用数组也是可以的。在使用指针时可以 用数组名 ,也可以用另外定义的指向数组的指针。 第四章 例 7: #include int a8=1,3,5,7,9,11,13; void fun(int *pa, int n) for(int i=0;in-1;i+) *(pa+7)+=*(pa+i); void main() int m=8; fun(a,m); /a是数组的数组名 ,是一个地址值 couta7endl; 运行结果: 49 第四章 3、 实参用数组名 , 形参用引用 。 采用这种情况时,应 先用类型定义语句定义一个 与实参数组类型相一致的 数组类型 。 四、内联函数: 1、 内联函数引 入 的原因 : 引入内联函数的目的是为了 提高 程序中函数调用 的效率问题 。引入内联函数, 在程序编译时 , 编译 器将程序中出现的内联函数的调用表达式用内联函数 的函数体来进行替换 ,因此, 引入内联函数 是以目标 代码的增加为代价来换取时间的节省。 第四章 2、 内联函数的定义方法 : 在函数头前加上关键字 inline,其格式: inline () 3、 使用内联函数应注意的事项 : (1)、内联函数通常情况下是将一些 函数体不大 ,而 且 使用频繁 的函数 ; (2)、内联函数体内 不允许用循环语句和开关语句 ; (3)、内联函数的定义必须出现在 第一次调用 之前; (4)、类体内定义的所有 成员函数都是内联函数 。 第四章 例 8、 编程求 1 10中各个数的平方。 #include inline int power_int(int x) return (x) * (x); void main() for (int i=1;i=10;i+) int p=power_int(i); couti * i=pendl; 运行结果:分别是 110 的平方。 第四章 第四节 函数的 重载 第四章 一 、函数重载定义: 函数重载: 是指同一个函数名对应着多个不同的 实现。 二、 定义重载函数时的注意事项: 1、 多个重载的同名函数在定义时要注意它们的参 数 的不同,主要是参数的 个数、类型和顺序 的不同。 2、在选择重载函数的不同实现时,主要根据参数不同 进行选择。 例 9、 求两个操作数之和。 #include int add(int, int); double add(double, double); 第四章 void main() coutadd(5, 10)endl; coutadd(5.0, 10.5)endl; int add(int x, int y) return x+y; double add(double a ,double b) return a+b; 程序的输出结果 : 15 15.5 第四章 例 10、 找出几个 int型数中最小者。 #include int min (int a , int b); int min (int a ,int b , int c); int min (int a ,int b ,int c ,int d); void main() coutmin(13, 5, 4, 9)endl; coutmin(-2, 8, 0); int min (int a ,int b) return ab? a :b; int min (int a ,int b ,int c) 第四章 int t=min(a, b); return min(t, c); int min(int a ,int b ,int c ,int d) int t1=min(a,b); int t2=min(c,d); return min(t1,t2); 运行结果: 4 -2 第四章 第五节 作用域 第四章 一、 用作标识符的作用域规则 : 作用域又称作用范围 。 在程序中出现的各种标识 符 ,它们的作用域是不同的。 标识符只能在说明它或定 义它的范围内是 “ 可见的 ” ,即 是可以进行存取或访问 操 作的 ; 而在该范围之外是 “ 不可见 ” 的 , 也就是 指不 可 以进行存取或访 问 操作的。 二、 作用域的种类 : 作用域的按大小可分为 : 1、程 序级 : 作用域最大 , 属于程序级作用域的有外部 函数和外部变量。 2、 文件级 : 仅在 所 定义的文件内 , 属于 文件级 作用域 的有内部函数和外部静态类变量。 第四章 3、 函数级 : 在它所定义的函数体内 , 属于函数级作用 域的有函数的形参和在函数内定义的自动类变量和 内部静态 类变量以及语句标号 。 4、 块级 :在某一程序块内, 属于块级作用域的有定 义在分程序、 if语句、 switch 语句以及循环语句中 的自动类变量和内部静态类变量。 三、 关于重新定义标识符的作用域规定 : 在某个作用范围内定义的标识符在该范围内的子 范围内中可以重新定义 , 这时原定义的标识符在子范 围内是不可见的 ,但是它还是存在的 ,只是在子范围内 由于出现了同名的标识符而被暂时地隐藏起来。 出 了 子范围后 ,它又是可见的。 第四章 第七节 存储类及系统函数 第四章 一、存储类: 1、变量的存储类: (1)、变量存储类的种类: 、自动类 : 是在函数体或分程序内定义的变量 , 定义时可加 auto说明符 ,也可以省略。 、寄存器类: 也 是定义在函数体内或分程序内 的变 量 ,定义时前边加说明符 rigester。寄存器类变量有 可能被存放到 CPU的通用寄存器中 , 此时 可提高存取 速度 ,但是由于 CPU的通用寄存器 数量有限, 如果没 被存放到通用寄存器中便按自动类变量处理。 、外部类: 是一种定义在函数体外 , 定义时不加任 何存储类说明的一种变量 。 外部变量在引用之前需 第四章 要说明 , 说明外部变量时应在 其 前面加说明符 extern。 外部变量的 定义和说明是两回事 : 在一个程 序中 ,一个外部变量 只能定义 一次 , 但是 可以说明 多次 。外部变量 不管是 在 同 一文件 中,还是在 另 外一个文件中 被 引用 , 都要 在引用前必须 对它进行 说明。 、静态类(内部静态和外部静态): 内部静态类变量 也 是在函数体内或分程序内定 义 的变量, 用说明符 static说明。它的作用域与自 动变量相同 ,但是它的生存期 (即寿命 )是长的 , 是一 种可见性与存在性不一致的变量 : 在定义它的作用 第四章 域外 ,它虽然不可见 ,但是它仍然存在 ,且没有被释放 掉 ,一旦它回到作用域后 ,仍然保留其原来的值 。 外部 静态类变量 被定义在函数体外, 也 用说明符 static说明 ,其作用域是文件级的, 可见性与存在 性 也是 不一致的 ( 它的作用域不是整个程序,但其 生存期却在整个程序)。 (2)、不同存储类变量的作用域和寿命: 、作用域分为程序级、文件级、函数级和分程序级 、寿命分为长和短两种。存放在内存的静态区的寿 命长,存放在寄存器和内存的动态区的寿命短。 2、函数的存储类 : (1)、函数存储类的种类: 函数存储类分两种: 内部函数和外部函数。 第四章 a、 内部函数 : 用关键字 static 说明的函数 , 也称 为 静态函数。在定义它的文件中可以被调用 ,而在同一 程序的其他文件中不可 被 调用。 定义格式 : static () b、 外部函数 : 用关键字 extern 说明的函数 ,其 作用 域在整个程序中 , 包含组成该程序的若干个文件。 定义格式 : 第四章 extern() 一般情况下 ,关键字 extern可以省略。 二、 系统函数 : 1、使用系统函数的注意事项 : C+系统将所提供的系统函数的说明分类放在不同 的 .h 文件中。因此 , 编程者在使用系统函数时 ,应该 注意 : ( 1)、 了解你所使用的 C+系统提供了哪些系统函 数。 第四章 (2)、 知道某个系统函数的说明在哪个头文件中。 ( 3)、 调用一个函数时 ,一定要将该函数的功能、参 数和返回值搞清楚 。 否则难以正确地使用 该 函数。 2、 字符串处理函数 : ( 1)、 字符串长度函数 strlen( ): 功能是返回一个 字符串的长度。 其 原型说明 为 : int strlen(const char *s); ( 2)、 字符串拷贝函数 strcpy( ): 功能是用一个字 符串去更新另一个字符串 ,从 而实现字符串的复 制。该函数原型说明 : char *strcopy(char *s1,const char *s2); char *strncpy(char *s1,const char *s2,int n); 第四章 (3)、 字符串连接函数 strcat( ): 功能是将一个字符 串添加到另一个字符串的后面 ,形成一个包含了两 个字符串的新字符串。 该 函数的原型说明 : char *strcat (char *s1,char *s2); char *strncat(char s1,char s2,int n); (4)、 字符串比较函数 strcmp( ): 功能是用来比较两 个字符串是否相等。如果该函数返回值为 0,说明比 较的两字符串相等 ;如果返回值为大于 O的值 ,说明比 较的两个字符串不相等 ,第一个大于第二个 ,如果返 回值为小于 O 的值 ,说明第一个小于第二个。 该函数的原型说明 : 第四章 .int strcmp(const char *s1,const char *s2) .int strncmp(const ch ar *s1,const char *s2,int n); 第四章 : 第四章 : 第四章 : 第四章 :
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!