第七章 用函数实现模块化设计
- 7.1 函数的说明
- (1)一个较大程序中,往往分为若干个程序模块(源程序文件),每个模块包含一个或多个函数,每个函数实现一个特定的功能。
- (2)在程序中如果函数定义在main函数之后,需要在main函数前或它内部的开头进行声明。
- (3)一个C程序包括多个源程序文件,一个源程序文件(包括函数、指令、数据声明与定义等)可以为多个C程序共用,它也是一个编译单位。
- (4)C程序的执行是从main函数开始和结束的,main函数只能被系统调用。
- (5)函数的定义不能嵌套,定义是相互独立的,函数间可以相互调用。
- (6)分类:① 库函数,用户自定义的函数;② 有参和无参函数。
- 7.2 函数的定义
- 7.2 .1 为什么要定义函数
- (1)指定函数的名字、函数值类型、函数实现的功能等信息通知编译系统,使之按照定义的功能执行.
- (2)包括:函数返回值类型(函数类型)、函数名、函数参数名及类型、函数功能。
- 7.2.2 定义函数的方法
- 1.定义无参函数:类型名 函数名(){ };或 类型名 函数名(void){ };
- 定义有参函数:类型名 函数名 (形参列表){ };
- 3.定义空函数:类型名 函数名(){ 无函数体 }。
- 7.2 .1 为什么要定义函数
- 7.3 函数的调用
- 7.3.1 调用函数的形式
- (1)一般格式:函数名(实参列表)
- (2)其他格式:1)函数名();2)函数表达式:c= max(a,b)+1; 3) 函数参数:c=max(a, max (c,d ))。
- 7.3.2 函数调用时的数据传递
- 形参和实参:实参可以是常量、变量、表达式
- 实参和形参间的数据传递(虚实结合):在调用函数过程中,系统会把实参的值传递给被调函数的形参,该值在调用期间有效。
- 3.说明:实参和形参的类型应相同或赋值兼容。
- 7.3.3 函数调用的过程
- 形参在未出现调用时不占据内存,调用时才被临时分配内存。
- 通过return 语句将函数值带回到主调函数,但是要注意返回值的类型要和函数值的类型一致,当不同时以函数值为准。
- 调用结束,形参单元被释放;如果一个函数被调用时形参的值改变,不会改变实参的值(实参传给形参是值传递—单向传递)。
- 7.3.4 函数的返回值
- 1.定义:希望通过函数调用使主调函数得到一个确定的值,这就是返回值(=函数值) 。
- 说明
- (1)通过return语句将一个确定值带回到主调函数中;一个函数可以有一个以上的return语句,其后的括号可以省略。
- (2)有返回值的函数在定义时要制定类型。
- 7.3.1 调用函数的形式
- 7.4 对被调用函数的声明和函数原型
- 1.在定义函数前要对函数进行声明,即:函数首部+分号;在检查函数调用时要求函数名、函数类型、参数顺序及个数要与声明一致,实参与形参类型一致。
- 声明的格式:① 函数类型 函数名 (参数类型1 参数名1 ,参数类型2 参数名2 ····);② 函数类型 函数名 (参数类型1 参数类型2 ····)
- 说明 :函数定义不等于函数声明,声明的作用: 把函数的有关信息告知编译系统,以便在调用该函数时按此进行检查。
- 7.5 函数的嵌套调用(理解)
- 函数不能嵌套定义但是可以嵌套调用
- 7.6 函数的递归调用(理解)
- 在调用一个函数的过程中又直接或间接出现调用该函数本身
- 一个递归问题分为:“回溯”,“递推”;见P183。
- 7.7 用数组作为函数参数
- 7.7.1 数组元素作函数实参
- 数组元素可以作为实参但是不能作形参(形参:临时分配, 数组在内存中占据连续的存储单元)。
- 数组元素作实参,形式与方向是“值传递”与单向传递。
- 7.7.2 一维数组名作参数
- 1.数组名可作实参和形参;数组元素作实参时,传递的的是数组元素的值,数组名作实参传递的是数组**首元素的地址值**。
- 注意:(1)用数组名作函数参数时,应当在主调函数和被调函数中分别定义数组;(2)实参形参类型要一致,可不指定形参数组大小;
- (3)形参数组首元素和实参数组首元素具有同一地址,共同占用一块内存,形参数组和实参数组的值同步变化;(4)编译时C系统把形参数组当指针变量处理,接收形参传递来的地址,用数组和指针变量作实参等价。
- 7.7.3 多维数组名作函数实参
- 1.用多维数组作参数,在对形参数组定义时可以指定每一维大小也可以省略第一维大小但是第二维的大小不能省略。
- 7.7.1 数组元素作函数实参
- 7.8 局部变量和全局变量
- 7.8.1 局部变量
- 1.定义的三种情况:在函数开头;函数的复合语句内定义;函数的外部
- 2.局部变量:只在本函数(定义变量的)内部定义或在本复合语句内定义;
- 3.说明:主函数中定义的变量也只在该函数内有效;形参也是局部变量。
- 7.8.2 全局变量(外部变量)
- 定义:在函数外定义的变量。全局变量可以被本文件中的其他函数所共用,它的有效范围:从定义变量的位置开始到本源文件结束。
- 说明:同一文件中的所有函数都能引用全局变量的值,一个函数中改变了全局变量的值也影响到其他函数中全局变量的值;在局部变量的作用范围内,全局变量的作用范围会被屏蔽,即不起作用。
- 7.8.1 局部变量
- 7.9 变量的存储方式和生命周期
- 7.9.1 动态和静态存储
- 1.从变量的存在周期(生存期)分为:静态存储和动态存储
- 2.静态存储:(1)程序在运行期间由系统分配固定的存储空间;(2)存储的数据:全局变量;说明:在程序开始时,给全局变量分配存储空间,程序结束时就释放。
- 3.动态存储:(1)指的是在程序运行期间根据需要进行动态分配存储空间;(2) 存储的数据:函数形参,自动变量(无static声明),返回地址等;说明:在开始调用函数时分配存储空间,调用结束时就释放。
- 在C语言中,每个变量和函数都有两个属性:数据类型和数据的存储类别;用户可以自定义存储类别也可以由系统指定(默认);存储类别包括4种:auto,static,register(寄存器变量-cpu),extern。
- 7.9.2 局部变量的存储类别
- 自动变量(auto):函数中的局部变量如果不专门声明为static,都是存储在动态存储区,还包括形参;这类变量随着函数的调用变化而存在或消失,关键字auto可省略。
- 静态局部变量(static):用途:在函数调用结束后局部变量的值不消失而保持上一次函数调用结束时的值。 说明:(1) 静态局部变量属于静态存储类别,区别于动态存储变量;(2) 对静态局部变量是在编译时赋初值的,只赋一次,之后调用函数只保留上次函数调用结束时的值;对自动变量赋值是在函数调用时进行的。(3)静态局部变量若在定义局部变量时不赋初值,系统会自动赋值0或空字符‘\0’(字符变量);静态存储缺点:它的内存长期不释放,多占用内存;降低程序的可读性。
- 7.9.3 全局变量的存储类别
- 1.全局变量存放在静态存储区,生存周期:是固定的即整个程序的运行过程;作用域:从变量定义处到文件末尾。
- 2.(1)在一个文件内扩展外部变量的作用域:在定义点前的函数在引用前用 extern 外部变量 进行声明;(2) 将外部变量的作用域扩展到其他文件:方法是在任一文件里定义外部变量A,而在另一文件里用extern对A作外部变量声明。(3)将外部变量的作用域限制在本文中:希望某些外部变量只在本文中使用而不能被其他文件引用,可采用关键字static 声明,该变量就是静态外部变量。
- 3.存储类别小结(见P210):用static声明变量的作用:(1)对局部变量 ,把它分配在静态存储区,使该变量在整个程序执行期间不释放。(2)全局变量:使该变量的作用域仅限于本文件。
- 7.9.1 动态和静态存储
- 7.10 内部函数和外部函数
- 函数本质上是全局的;可以被本文件中的其他函数调用也可被其他文件中的函数调用。
- 7.10.1 内部函数(静态)
- 函数只能被本文中的其他函数调用
- 格式:static 类型名 函数名(参数列表)
- 位置:前面加上static,放在文件的开头。
- 7.10.2 外部函数
- 在定义函数时在其前面加上extern ,C语言规定,如果在定义函数时省略extern则默认为外部函数。
- 使用:在调用此函数的其他文件中用extern作函数声明。
