C语言程序设计(第四版)第七章主要内容

本章主要讲述了<函数与模块化程序设计>

一、函数的定义

1.程序都是从main()的入口开始,到main()的出口结束。

函数可分为标准库函数和自定义函数。

2.使用ANSI C的库函数时,必须在程序的开头把该函数的头文件包含起来。

3.函数使用前必须先定义。

格式:

返回值类型 函数名(类型 形式参数1,类型 形式参数2,...)

{

声明语句序列

可执行语句序列

}

4.通常变量名用小写字母开头的单词组合而成,使用"名词"或者"形容词+名词"的形式。

函数名用大写字母开头的单词组合而成,使用"动词"或者"动词+名词"的形式。

5.在函数体内部定义的变量只能在函数体内访问,称为内部变量,也是形式参数。

6.若函数没有函数返回值,则需用void定义返回值的类型。

注意:在函数定义的前面写上一段注释来描述函数的功能及其形参,是一个非常好的编程习惯。

二、向函数传递值和从函数返回值

1.函数不能嵌套定义。

2.函数的返回值只能有一个,函数返回值的类型的可以是除数组以外的任何类型。函数中的return语句可以有多个,但不表示函数可以有多个返回值。

3.当函数返回值类型为void类型时,表示函数没有返回值,函数可以没有return 语句,程序一直运行到函数的最后一条语句后再返回。如果程序不是运行到函数的最后一条语句才返回,那么必须使用return 语句返回,无须返回任何值的return语句可写成

return;

4.若定义main()时未显示指明其返回值类型,也未使用void,则其返回值将被默认为int类型。

5.自定义函数例子:

注意:当函数在主函数后面时,要在主函数里面添加声明。

6.函数的数量必须与形参相等,它们的类型必须匹配,匹配的原则与变量赋值的原则一样。

三、函数的递归调用和递归函数

1.如果一个对象部分地由它自己组成或按它自己定义,则我们称它是递归。

2.经典例子:

3.任何递归函数都必须至少有一个基线情况,并且一般情况必须最终能转化为基线情况,否则程序将无线递归下去,导致程序出错。

4.每个迭代程序原则上都可以转换成等价的递归程序,反之不行。

四、变量的作用域和生存期

1.变量的作用域规则:每个变量仅在定义它的语句块内有效,并且拥有自己的存储空间。

2.全局变量的作用域为整个程序,即全局变量在程序的所有位置均有效。

3.全局变量未赋值时,自定义初始化为0。

4.形参值的改变不会影响实参,因为实参与形参分别占据着不同的存储单元。

5.在并列的语句块之间只能通过一些特殊通道传递数据,如函数参数、返回值,以及全局变量。

6.变量的存储类型一般声明如下:

存储类型 数据类型 变量名表;

7.自动变量(动态局部变量)

标准定义格式:

auto 类型名 变量名;

如果没有指定变量的存储类型,那么变量的存储类型就缺省为auto。

特点: (1)自动变量在定义时不会自动初始化;

(2)自动变量在退出函数后,其分配的内存立即被释放。

8.静态变量

标准定义格式:

static 类型名 变量名;

特点:在下一次进入函数时,静态局部变量的值仍保持上一次退出函数前所拥有的值。

9.外部变量

声明格式:

extern 类型名 变量名;

作用域是它的定义点到本文件的末尾。

和静态变量一样,外部变量也是在静态存储区内分配内存的,其生存期是整个程序的运行期。没有显示初始化的外部变量由编译程序自动初始化为0。

静态局部变量只能在定义它的函数内被访问,静态全局变量可以在定义它的文件内的任何地方被访问,但不能像非静态的全局变量那样被程序的其他文件所访问。

10.寄存器变量

定义格式:

register 类型名 变量名;

它可以避免CPU对存储器的频繁数据访问,使程序更小、执行速度更快。

五、模块化程序设计

1.模块分解的基本原则:高聚合、低耦合,保证每个模块的相对独立性。

2.把需要共享的函数放在一个单独的.c文件中,把共享函数的函数原型、宏定义和全局变量声明等放在一个单独的.h头文件中,其他需要共享这个函数的程序用#include包含这个头文件后,就可以调用这个函数了。因头文文件<stdio.h>几乎在每个文件中都要使用,因此几乎每个文序设 件都要包含这个头文件。

3.对于系统提供的标准库函数的头文件,通常用尖括号包含头文件。

4.头文件里对全局变量的声明要加上extern关键字,用以声明该变量为外部变量。变量声明与变量定义不同的是:对于变量声明,编译器并不对其分配内存,因为这个变量实际是在其他模块定义的,即希望这个变量的内存是在其他模块分配的,用extern声明表示要使用在其他模块定义的变量。如果模块内不允许使用模块外定义的函数和全局变量,只要在定义它们时加上static关键字,就能保证只能在该模块内使用它们了。

5.assert()的功能是在程序的调试阶段验证程序中某个表达式的真与假,使用assert()的源文件中只需包含头文件<assert.h>即可。

6.在下面几种情况中才考虑使用断言:

(1)检查程序中的各种假设的正确性,例如一个计算结果是否在合理的范围内。

(2)证实或测试某种不可能发生的状况确实不会发生,例如一些理论上永远不会执行到的分支(如switch的default:后)确实不会被执行。

assert(断言)仅能用于调试程序,不能作为程序的功能。

相关推荐
结衣结衣.9 分钟前
python中的函数介绍
java·c语言·开发语言·前端·笔记·python·学习
五味香39 分钟前
C++学习,信号处理
android·c语言·开发语言·c++·学习·算法·信号处理
梓䈑1 小时前
【C语言】自定义类型:结构体
c语言·开发语言·windows
PYSpring1 小时前
数据结构-LRU缓存(C语言实现)
c语言·数据结构·缓存
TANGLONG2221 小时前
【C语言】数据在内存中的存储(万字解析)
java·c语言·c++·python·考研·面试·蓝桥杯
@qike2 小时前
【C++】—— 日期类的实现
c语言·c++·笔记·算法·学习方法
f狐0狸x3 小时前
C语言指针plus版练习
c语言·指针
江奖蒋犟3 小时前
【初阶数据结构】排序——归并排序
c语言·数据结构·算法
无限大.4 小时前
c语言实例 -- 循环链表
c语言·开发语言·链表
Stark、4 小时前
异常处理【C++提升】(基本思想,重要概念,异常处理的函数机制、异常机制,栈解旋......你想要的全都有)
c语言·开发语言·c++·后端·异常处理