《C语言入门经典(第四版)9-函数再探.doc》由会员分享,可在线阅读,更多相关《C语言入门经典(第四版)9-函数再探.doc(4页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、 本文由泽五令贡献 ppt文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机查看。 C入门经典(第4版) 入门经典( 第09章 函数再探 09章 学习了第8 学习了第8章后,读者就应具备创建和使用函数的基础知识了.本章将以 此为基础,介绍函数的使用和操作,尤其是如何通过指针访问函数,也会使用 一些更灵活的方法在函数之间通信 . C入门经典(第4版) 入门经典( 9.1 函数指针 指针对于操作数据和含有数据的变量是一个非常有用的工具.只要一把 火钳就可处理所有火热的东西,同样,使用指针也可以操作函数,函数的内存 地址存储了函数开始执行的位置(起始地址) 地址存储了函数开始执
2、行的位置(起始地址),存储在函数指针中的内容就是这 个地址 . 声明函数指针 通过函数指针调用函数 函数指针数组 作为变元的函数指针 C入门经典(第4版) 入门经典( 9.1.1 声明函数指针 .1.1 声明函数指针 函数指针的声明看起来有点奇怪,容易混淆,所以下面从一个简单的例子开始: int (*pfunction) (int); C入门经典(第4版) 入门经典( 9.1.2 通过函数指针调用函数 .1.2 假定定义如下函数原型: int sum(int a, int b); /* Calculates a+b */ 这个函数有两个int类型的参数,返回值的类型是int,所以可以把它的地址
3、存储 这个函数有两个int类型的参数,返回值的类型是int,所以可以把它的地址存储 在如下函数指针中: int (*pfun)(int, int) = sum; C入门经典(第4版) 入门经典( 9.1.3 函数指针数组 .1.3 函数指针和一般的变量是一样的,所以可创建函数指针的数组.要声明 函数指针数组,只需将数组的大小放在函数指针数组名之后.例如: int (*pfunctions10) (int); 这条语句声明了一个包含10个元素的pfunctions数组.这个数组里的每个 这条语句声明了一个包含10个元素的pfunctions数组.这个数组里的每个 元素都能存储一个函数的地址,该函
4、数有两个int类型的参数,返回类型是int. 元素都能存储一个函数的地址,该函数有两个int类型的参数,返回类型是int. C入门经典(第4版) 入门经典( 9.1.4 作为变元的函数指针 .1.4 也可以将函数指针作为变元来传递,这样就可以根据指针所指向的函数, 而调用不同的函数了 . C入门经典(第4版) 入门经典( 9.2 函数中的变量 将程序分解成函数,不仅简化了开发程序的过程,还增强了程序语言解 决问题的能力.设计优良的函数常常可以重用,使新应用程序的开发变得更快, 更简单.标准库就证明了可重用函数的威力.函数中变量的特性以及C 更简单.标准库就证明了可重用函数的威力.函数中变量的特
5、性以及C语言在 声明变量时提供的一些额外功能进一步增强了程序语言的力量 . 静态变量:函数内部的追踪 在函数之间共享变量 C入门经典(第4版) 入门经典( 9.2.1 静态变量:函数内部的追踪 前面使用的所有变量在执行到定义它的块尾时就超出了作用域,它们在 堆栈上分配的内存会被释放,以供另一个函数使用.这些变量称为自动变量, 因为它们是在声明时自动创建的,在程序退出声明它的块后自动删除.这是一 种非常高效的过程,因为只要正在执行的语句在声明变量的函数内,函数中包 含数据的内存就会一直保存该数据 . C入门经典(第4版) 入门经典( 9.2.2 在函数之间共享变量 也可以在所有的函数之间共享变量
6、.常量在程序文件的开头声明,所以 常量位于组成程序的所有函数的外部) 常量位于组成程序的所有函数的外部),同样,也可以采用这种方式声明变量, 这种变量称为全局变量(global variables),因为它们可以在任意位置访问.它 这种变量称为全局变量(global variables),因为它们可以在任意位置访问.它 的声明方式和一般变量相同,但声明它的位置非常重要,这个位置确定了变量 是否为全局变量 . C入门经典(第4版) 入门经典( 9.3 调用自己的函数:递归 函数调用自己称为递归,递归在程序设计中不常见,所以本节仅介绍概 念,不过在某些情况下,这是一个效率很高的技巧,可以显著简化解
7、决特定问 题所需的代码.递归也有几个坏处,但这里也不涉及 . C入门经典(第4版) 入门经典( 9.4 变元个数可变的函数 printf() 在标准库中,某些函数的变元数是可变的,例如函数printf()和scanf().有 在标准库中,某些函数的变元数是可变的,例如函数printf()和scanf().有 时需要这么做,所以标准库提供了编写这种函数的例程 时需要这么做,所以标准库提供了编写这种函数的例程 . 复制va_list 复制va_list 长度可变的变元列表的基本规则 C入门经典(第4版) 入门经典( 9.4.1 复制va_list 复制va_list 有时需要多次处理可变的变元列表
8、.头文件为此定义了一个复 有时需要多次处理可变的变元列表.头文件为此定义了一个复 制已有va_list的例程.假定在函数中使用va_start()创建并初始化了一个va_list 制已有va_list的例程.假定在函数中使用va_start()创建并初始化了一个va_list 对象parg,现在要复制parg: 对象parg,现在要复制parg: va_list parg_copy; copy(parg_copy, parg); C入门经典(第4版) 入门经典( 9.4.2 长度可变的变元列表的基本 规则 以下是编写变元数目可变的函数的基本规则: 在变元数目可变的函数中,至少要有一个固定变元.
9、 必须调用va_start()初始化函数中可变变元列表指针的值.变元指针的类 必须调用va_start()初始化函数中可变变元列表指针的值.变元指针的类 型必须声明为va_list类型. 型必须声明为va_list类型. 必须有确定每个变元类型的机制.可以假设默认的类型,或用一个参数 来指定变元的类型.例如,在average()函数中,可以有另一个固定的变元, 来指定变元的类型.例如,在average()函数中,可以有另一个固定的变元, 它的值是0时,表示变元的类型是double,它的值是1 它的值是0时,表示变元的类型是double,它的值是1时,表示变元的类型是 long.如果在va_ar
10、g()调用中指定的变元类型不对应于调用函数时指定的变元 long.如果在va_arg()调用中指定的变元类型不对应于调用函数时指定的变元 值,函数就不能正常工作. C入门经典(第4版) 入门经典( 9.5 main()函数 main()函数 main()函数是程序执行的起点.这个函数有一个参数列表,在命令行中执 main()函数是程序执行的起点.这个函数有一个参数列表,在命令行中执 行程序时,可以给它传递变元.main()函数可以有两个参数,也可以没有参数. 行程序时,可以给它传递变元.main()函数可以有两个参数,也可以没有参数. main()函数有参数时,第一个参数的类型是int,表示在
11、命令行中执行 main()函数有参数时,第一个参数的类型是int,表示在命令行中执行 main()函 main()函 数的参数个数,包含程序名在内.第二个参数是一个字符串指针数组. 因此,如果在语句行中,在程序名称的后面添加两个变元,main()函数的第一 因此,如果在语句行中,在程序名称的后面添加两个变元,main()函数的第一 个变元值就是3,第二个参数是一个包含3 个变元值就是3,第二个参数是一个包含3个指针的数组,第一个指针指向程序 的名称,第二和第三个指针是指向在命令行上输入的两个变元 . C入门经典(第4版) 入门经典( 9.6 结束程序 结束程序的方法有几种.执行到main()函
12、数体的结尾,就等于执行main() 结束程序的方法有几种.执行到main()函数体的结尾,就等于执行main() 中的return语句,结束程序.另外,调用两个在头文件中声明的标准 中的return语句,结束程序.另外,调用两个在头文件中声明的标准 库函数可以结束程序,一个是abort()函数,它可以立即终止程序,并表示程序 库函数可以结束程序,一个是abort()函数,它可以立即终止程序,并表示程序 操作是非正常结束,所以对于正常结束的程序不应使用这个函数 . C入门经典(第4版) 入门经典( 9.7 函数库:头文件 编译器提供了许多在头文件中声明的标准函数.头文件也称为包含文件, 它们是开
13、发应用程序时必要的资源.前面已经见过一些头文件,因为头文件是 C编程的一个基本组成部分 . C入门经典(第4版) 入门经典( 9.8 提高性能 有两个工具可以使编译器生成性能更高的代码.其中一个与短函数调用 的编译方式相关,另一个涉及指针的使用.但不能保证其效果,而是取决于编 译器的实现方式.这里先探讨短函数 . 内联声明函数 使用restrict关键字 使用restrict关键字 C入门经典(第4版) 入门经典( 9.8.1 内联声明函数 C语言的功能结构要求将程序分解为许多函数,函数有时可以非常短.短 函数的每次调用可以用实现该函数功能的内联代码替代,提高执行性能 . C入门经典(第4版)
14、 入门经典( 9.8.2 使用restrict关键字 使用restrict关键字 专业的C 专业的C编译器可以优化对象代码的性能,这涉及到改变在代码中为操作 指定的计算顺序.为了优化代码,编译器必须确保操作的这种重新排序不影响 计算的结果,并用指针指出这方面的错误.为了优化涉及指针的代码,编译器 必须能肯定指针是没有别名的换言之,每个指针引用的数据项都没有在给 必须能肯定指针是没有别名的换言之,每个指针引用的数据项都没有在给 定范围内以其他方式引用.关键字restrict就可以告诉编译器,何时出现这种情 定范围内以其他方式引用.关键字restrict就可以告诉编译器,何时出现这种情 况,并允许
15、应用代码优化功能 . C入门经典(第4版) 入门经典( 9.9 使用restrict关键字 使用restrict关键字 到此函数已经介绍完毕,我们的C 到此函数已经介绍完毕,我们的C语言学习之旅也已过半,一些不太复杂 的问题应该都可以解决.接下来的这个程序将用到目前学过的各种C 的问题应该都可以解决.接下来的这个程序将用到目前学过的各种C元素 . 问题 分析 解决方案 C入门经典(第4版) 入门经典( 9.9.1 问题 现在要编写一个游戏.选择编写游戏程序有几个理由.首先, 现在要编写一个游戏.选择编写游戏程序有几个理由.首先,游戏比其他类型 的程序复杂,即使是比较简单的游戏程序.其次,游戏比
16、较有趣! 的程序复杂,即使是比较简单的游戏程序.其次,游戏比较有趣! C入门经典(第4版) 入门经典( 9.9.2 分析 这个问题的分析和以前所见的稍有不同.本章介绍的重点是结构化编程, 换句话说,就是将一个大问题分解成许多小问题逐一解决,这就是为什么要花 这么多时间介绍函数的原因 . C入门经典(第4版) 入门经典( 9.9.3 解决方案 首先,建立并显示棋盘.为了使游戏程序比较短,使用比较小的棋盘 (66).但这里在程序中通过一个预处理器指令将棋盘的大小设置为一个符号, (66).但这里在程序中通过一个预处理器指令将棋盘的大小设置为一个符号, 以便在以后改变棋盘的大小.使用一个独立的函数显示棋盘,因为这是一个自 包含的动作. C入门经典(第4版) 入门经典( 9.10 小结 如果读者到目前为止都没有遇到什么大问题,说明您将成为一位有能力 的C程序员.本章和前一章介绍了编写结构优秀的C程序所需的所有知识,函 程序员.本章和前一章介绍了编写结构优秀的C 数结构是C语言的核心,要尽量使函数短小精悍,意图明确.这是优秀C 数结构是C语言的核心,要尽量使函数短小精悍,意图明确.这是优秀C代码 的本质.现在读者应该能够使用函数结构去处理自己的编程问题了 .1