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(断言)仅能用于调试程序,不能作为程序的功能。

相关推荐
~yY…s<#>1 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
EricWang13583 小时前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
我是谁??3 小时前
C/C++使用AddressSanitizer检测内存错误
c语言·c++
希言JY4 小时前
C字符串 | 字符串处理函数 | 使用 | 原理 | 实现
c语言·开发语言
午言若4 小时前
C语言比较两个字符串是否相同
c语言
TeYiToKu6 小时前
笔记整理—linux驱动开发部分(9)framebuffer驱动框架
linux·c语言·arm开发·驱动开发·笔记·嵌入式硬件·arm
互联网打工人no16 小时前
每日一题——第一百二十四题
c语言
爱吃生蚝的于勒6 小时前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
羊小猪~~6 小时前
数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看
c语言·数据结构·c++·考研·算法·链表·visual studio
洋2406 小时前
C语言常用标准库函数
c语言·开发语言