C语言9-函数1

摘要:本文系统介绍了函数编程的核心概念,主要包括:1)函数的定义、调用和声明三种形式;2)变量的作用域(局部/全局变量)和生存周期;3)四种存储类型(auto/register/extern/static)及其内存分配机制;4)函数参数传递规则及递归函数的使用要点。重点解析了栈区、堆区、数据区和文本段的内存分布特点,通过闰年判断和四则运算实例演示函数封装方法,并以汉诺塔问题为例说明递归函数的应用逻辑。全文从理论到实践,系统阐述了函数编程的关键知识点。

一、函数的概要

1、作用:

                避免重复性代码、让程序更加模块化;

2、三种形式:

                函数的定义、函数的调用、函数的声明;

二、函数的定义

1、功能:定义一个函数的实现;

2、基本形式:

三、函数的调用

1、功能:跳转去使用一个函数

2、基本形式:

3、分类:

主调函数:主动调用别的函数的函数称为主调函数;

被调函数:被主调函数调用的函数称为被调函数;

四、函数的声明

1、功能:声明函数的参数及特性

2、要求:

(1)如果被调函数在主调函数的下方定义需要再主调函数上方声明

(2)如果被调函数在主调函数的上方定义,定义时已经完成函数的声明

五、变量的作用域和生存周期

(一)、作用域

1、定义:能够使用变量的范围称为变量的作用域

2、分类:

(1) 局部变量:变量作用域在离定义该变量最近的大括号内

(2) 全局变量:变量作用域在整个工程代码中,任意位置都可以使用全局变量

(二)、生存周期

1、定义:变量从开辟空间到空间被回收的过程称为生存周期

2、分类:

(1) 局部变量:

                执行到变量定义时,为变量开辟内存空间;

                代码执行超过变量作用域,回收变量空间;

(2) 全局变量:

                编译时分配全局变量空间;

                代码运行结束后回收变量空间;

(三)、存储类型

1、基本形式:存储类型 数据类型 变量名;

2、存储类型:

(1)auto(默认存储):自动型存储,将变量存放在栈空间中

(2)register:寄存器存储,将变量存放在CPU内部的寄存器中,如果寄存器存放等价于auto类型

(3)extern:声明一个变量是外部存放的

(4)static:静态存储,将变量存放在静态区中

3、代码运行时计算机内部空间分配:

具体内存区域

(1)栈区(.stack)

  • 位于内核区域的上部,紧挨着内核的顶部。
  • 栈区通常用于存储函数调用的局部变量、函数参数和返回地址等信息。
  • 栈区空间有上限的,默认(8M),不要定义太大空间
    栈区是操作系统管理区域,频繁被申请释放,所以未经初始化值为随机值
    代码执行到变量定义时开辟空间(栈空间),代码执行超过变量作用域回收空间(栈空
    间)
  • static关键字的作用:   
    • 如果用static修饰,会在程序结束时回收空间
    • 延长变量的生存周期,局部变量超过作用域被回收
    •  static修饰变量,将变量存放在数据区中,未经初始化时值为0值
    •  static限定全局变量作用域只能在本文件中使用
    • static防止全局变量或者全局函数重名

(2)堆区(.heap)

  • 在栈区的下方。
  • 堆区用于动态分配内存,通常在程序运行时根据需要分配

(3)数据区

  • 特点:
    存放全局变量和静态变量,未经初始化时会初始化为0值
    程序编译时分配空间
    程序结束时回收空间
  • 包含三个子区域:
    • .data:已初始化全局变量/静态变量区域(存放初始化的全局变量和静态变量)
    • .bss:未初始化全局变量/静态变量区域(在程序运行时会对.bss端初始化为0值)
    • .rodata:字符串常量区(区域中的内容不能修改,修改的话会导致段错)
  • 这些区域用于存储程序中的全局变量和静态变量,其中.rodata通常用于存储只读数据。

(4)文本段(.text)

  • 位于整个内存布局的最底部。
  • 文本段通常用于存储程序的可执行代码,这部分内存区域在程序运行期间通常是只读的。
  • 存放函数、代码和指令

如图所示:

六、函数调用

1、基本形式:函数名(实参1,实参2,....);

2、注意事项:

        实参个数与形参个数需要匹配

        实参与形参类型不一致时,会将实参类型转换为形参类

3、函数调用时参数的传递:

        函数调用时实参会将值传递给形参(形参是实参的副本)

4、小试牛刀:封装一个函数传入一个年份,判断该年是否为闰年

个人注解:

  • 先写c语言基本框架,头文件,main函数,返回值;
  • 定义变量,题目判断是否为闰年,所以可以定义变量year;此外我们还需要定义一个变量接受封装函数的返回值(定义ret可以,也可以定义其他名good只为演示可同名也可不同名);good = 封装函数名IsleepYear(实际参数year)
  • 开始写封装函数,先写好封装函数名和定义好形式参数,实际参数和形式参数对应。大括号内写满足闰年的条件,其次是函数结束后的返回值。

5、小试牛刀2:封装一个函数传入两个数字,计算加减乘除。

个人注解:

  • 封装函数就相当于集成好的计算器,里面有我们能够实现各种功能的函数。当我们要计算时两个数相加,输入实际参数(num1,num2)选好能像实现其的功能函数名(add),即可得出结果。
  • 现在我们就是承担编程好计算器功能,使它能够实现加减乘除的功能。

六、递归函数

1、 定义:函数体定义时调用函数体本身称为递归函数;

2、基本形式:

注意事项:

递归函数一定要有结束条件、避免深层次的递归调用

3、小试牛刀:汉诺塔盘子移动问题

个人注解:

        先假设将5盘子从A移动到C,有个中间区域B可以使用。运用递归函数的话就慢慢简化,过程差不多就是我们先假设先把前四个盘子移动到B,剩下第五个盘子移到C(最后一个盘子最大,它放哪里都可以所以可以不用考虑)。这时我们就把前四个盘子移回A,要想把盘子都移动到C,按照刚刚的思考,我们就可以先把前三个盘子移动到B,剩下第四个盘子(在其他盘子中是最大的,放哪里都不影响,所以不用考虑),依次递归减下去。就可以简化问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值