【笔记】【C语言】第七章 用函数实现模块化程序设计

  • 函数的概念
  • 函数的定义与调用
  • 函数的递归调用
  • 变量的作用域
  • 函数的作用域

 

7.1 函数的作用

(1)函数的作用

  将 较大的程序 划分为若干个 程序模块。每个模块实现一个特定的功能。

  在高级语言中,用子程序实现模块功能。

  函数间的调用关系:同一个函数可以被一个或多个函数调用任意次。

(2)

  一个C程序 由一个或多个程序模块组成。

  每个程序模块 作为一个源程序文件。

(3)

  一个源程序文件 由一个或多个 函数以及其他内容(命令行、数据定义等)组成。

  一个源程序文件 是一个编译单位

(4)

  C程序执行从main函数开始,在main函数结束。

  函数之间平行。即定义时不能嵌套定义。 

  函数间不能嵌套定义。可以相互调用,但不能调用main函数。 (main函数由系统调用)

(5)

  使用角度,分为:

  1.   标准函数(库函数):由系统提供。
  2.   用户自己定义的函数

  函数形式,分为:

  1. 无参函数
  2. 有参函数:主调函数 向 被调用函数 传递数据。

 

7.2 定义函数

(0)对函数功能的确立

(1)一般形式

类型标识符 函数名 ( 形式参数表列 )
{
    声明部分
    语句部分
    return () ; 
} 

(2)形式参数 实际参数 函数返回值

  定义函数时,称为形式参数。在主调函数中调用时,称为实际参数。

  return () ; 后的值作为函数带回的值(不需要函数返回值,可以不写return 语句)

  在不同的函数间,传输数据——参数,返回值,全局变量

(3)

  形参在未被调用时,不占存储单元。

  只有在调用时,才被分配内存单元,调用结束后,所占的内存单元被释放。

(4)

  实参可以使常量、变量、表达式。但要求有确定的值。

  与形参的类型应该相同或者赋值兼容。

  字符型与整型可以互相通用。

  实参与形参对数据的传递是“值传递”。

(5)

  函数的返回值应该属于某一个确定的类型。 若是定义时指定类型,应该符合。

  在C语言中,凡是不加类型说明的函数,自动按 整型 处理。

  若return 中表达式的值 与函数类型 不同,以函数类型为准。

 

7.3 函数调用

(1)一般形式:函数名(实参列表)

(2)对实参的求值顺序,各系统并不一致。

(3)调用方式:

  1. 函数(作为)语句
  2. 函数表达式
  3. 函数参数(实际同2)

(4)声明:把函数名和函数参数的个数及函数参数类型等信息通知编译系统,以便在遇到函数调用时,编译系统能正确认识函数并检查函数调用是否合法。

  库函数:文件开头用#include 命令,将调用有关库函数时所需用到的信息“包含”到本文件中。

  自己定义的函数:应在主调函数中 对被调函数作声明

  若被调函数定义出现在主调函数前,则不用声明。

(5)

  C语言不能嵌套定义函数,但可以嵌套调用

(6)递归调用:

  在调用一个函数的过程中,直接或间接地调用该函数本身,称为函数的递归调用。

  基本条件:用于控制递归调用结束。每个递归函数必须至少有一个基本条件,能用非递归的计算方式得到。

  一般条件:控制递归调用向着基本条件的方向转换。一般条件必须最终能转化为基本条件。

 

7.7 数组 作为函数参数

(1)数组元素 可以作为 实参,单向传递(值传递)。

(2)数组名 作为 实参。此时形参应当用数组名/指针变量。

  可以不定义长度。

  例如:

  float average ( float arr[ ] , int n ) 

  引用时:average ( a , a_len ) 或者 average ( &a[0] , a_len )

  float average ( float arr[10] , int n )

  float average ( float  * g )

(3)多维数组名 作为 实参。

  与初始化的规则较为相似,

(5)二维数组  

  如果对全部元素都赋初值,则定义数组时对第一维的长度可以不指定,但第二维的长度不能省。

  int a[3][4]或者   int a[][4]

  引用也是如此。

 

7.8 局部变量和全局变量

(1)内部变量:

    在函数内部定义的变量。作用范围只有定义后 到 函数内部。

  外部变量:

    在函数外定义的变量。全局变量可以为 本文件 中的其他函数所共用。有效范围:定义位置 到 本源文件结束。

(2)不同函数中可以使用相同名字的变量,代表不同的对象。他们在内存中占用不同的单元。

(3)形参也是局部变量。

(4)在一个函数内部,可以在复合语句中定义变量,

  这些变量只在本复合语句中有效,这种复合语句也称为“分程序”或“程序块”

 

(5)建议限制使用变量,将函数做成封闭体。

  ①全局变量在程序的全部执行过程中,都占用 存储单元 。

  局部变量尽在需要时才 开辟单元 。

  ②全局变量过多,会降低程序的清晰性,难以判断全局变量的值。

  ③降低了函数的通用性,移植函数时还需要移植有关的外部变量及其值。

  ④降低了可靠性,可能出现同名变量。

 

(非考试重点)

7.9 变量的存储类别

(1)从变量作用域(空间)角度,分为局部变量,全局变量。

  从变量值存在的时间(生存期)角度,分为静态/动态存储方法。

(2)动态存储方式:在程序运行期间,根据需要进行动态的分配存储空间的方式

  静态存储方式:在程序运行期间,由系统分配固定的存储空间的方式。

(3)存储空间分为:

  1.   程序区
  2.   静态存储区
  3.   动态存储区

(4)C中变量/函数 有两个属性:数据类型 和 数据的存储类别。

(5)存储类别:静态存储类 动态存储类:

  自动的(auto) :自动变量

    函数中的局部变量,未声明static存储类别,都是动态分配存储空间,数据存储在动态存储区

    在调用该函数的时候,系统会给他们分配存储空间,调用结束,自动释放这些空间。

    未赋值则值不确定,因为下次重新另外分配空间,分配的单元中的值是不确定的。

  静态的(static):

    有时需要保留函数中局部变量的值,则指定该局部变量为“静态局部变量”。数据存储在静态存储区

    静态局部变量实在编译时进行赋值,往后函数调用时,每次重新进行一次赋值语句。

    若是未定义初值,则编译时自动赋初值为0/空字符。

    静态局部变量结束后仍存在,但其他函数不能引用他们。

  寄存器的(register):寄存器变量

    一般情况,变量存储在内存中。当程序需要使用时,由控制器发出指令将内存中该变量的值送到运算器中。经过运算后,若要存储,再从运算器将数据送到内存中存放。

    如果某变量使用频繁,则可以将局部变量的值存放在CPU中的寄存器中,需要时直接从寄存器中存取

  外部的(extern):外部变量

    作用域是从定义处开始,到本程序文件的末尾。用extern声明外部变量,以扩展外部变量的作用域。

(6)用static声明外部变量

  外部变量,但只限于本文件引用。

  static使全局变量局部化,局限于本文件内。

 

(7)变量的声明和定义

  建立存储空间的声明,称为定义;不需要建立存储空间的声明,称为定义。(此处声明为狭义,指非定义性声明)

(8)存储类别小结:

从作用域分:

  局部变量:

    自动变量(离开函数,值就消失)

    静态局部变量(离开函数,值仍保留)

    寄存器变量(离开函数,值就消失)

  全局变量:

    静态外部变量(只限文本引用)

    外部变量(允许其他文件引用)

从生存期分:

  动态存储:

    自动变量(本函数有效)

    寄存器变量(本函数有效)

    形式参数(本函数有效)

  静态存储:

    静态局部变量(函数内有效)

    静态外部变量(本文件有效)

    外部变量(其他文件可引用)

从变量值存储的位置区分:

  内存中静态存储区:

    静态局部变量

    静态外部变量(函数外部静态变量)

    外部变量(可为其他文件引用)

  内存中动态存储区:

    自动变量和形式参数

  CPU中寄存器:

    寄存器变量

 

7.10 内部函数 和 外部函数
(1)函数的本质是全局的,也可以指定函数不能被其他文件调用。

(2)内部函数:

  一个函数只能被本文件中其他函数所调用。

  static 类型标识符 函数名(形参表)

(3)外部函数:

  可供其他文件调用。 默认外部函数。

  extern 类型标识符 函数名 (形参表)

posted @ 2022-04-21 17:16  心若笺诗  阅读(493)  评论(0编辑  收藏  举报