一、函数(function)

(1)函数的实现

        语法

        类型标识符 函数名(形式参数)   --- 函数头

        {

                //声明部分

                //语句部分

                函数体

                return 表达式;//返回函数处理的结果。

        }

(2)函数头

①类型标识符   ---int/shoet/long…

        返回值类型        //说明函数返回的结果的数据类型。

注意:

        1.返回值结果和设计的类型标识符可能不一致,此时,返回值结果会被转换成类型标识符指定的类型。

        2.如果返回信类型省略不写,默认 int类型。

        3.如果不需要带出返回值,使用void--- 空类型,对应的 return 后面不能有值。

②函数名   ---标识符,体现函数的功能(见名知义)

注意:

        1.形参与实参,类型匹配,个数相同。

        2.每个形参变量都必须明确指定类型。

        3.如果函数功能,不需要传入数据时,形参一般设计为 void。

③形式参数   ---本质是是变量

作用--用来接受 实际的参数。

语法:

        类型 形参变量名1,形参变量名2…

④函数体:函数对应功能,具体代码。

(3)函数定义的位置

        c语言中所有标识符--先定义,后使用,main的数是整个程序的入口函数,定义的位置在main之前,如果在main之后,在使用前在做一下函数声明(将函数头复制加上分号)。

(4)函数基本模型

实参 --->[功能模块] --->结果

eg:

        实现函数,对两个整形数据求和。

        step1:从功能出发,确定函数名---add。

        step2:从函数模型(数据处理的模型)出发,考虑,要处理那些数据(形参的个数,类型)。

                eg:int a,int b

        step3:考虑数据处理的功能   ---具体代码。

        eg:

                int sum;

                sum=a+b;

        step4:考虑结果的处理。

        eg:

                return sum;

 (5)函数调用

                ---使用函数 //使用这个功能。

        函数名   (实际参数)

(6)函数设计原则

        ①单一职责。

        ②高内聚,低耦合。

(7)函数传递数据

        全局变量   --- 不建议使用,会破坏c语言的结构化编程。

        形参变量   ---推荐。

二、函数的嵌套调用

(1)特殊的嵌套调用

           --- 自己调用自己。

(2)函数为什么会嵌套调用

        函数能够实现层层调用,本质上是因为有栈这个空间存在。

(3)栈

        1.是内存上的一块空间。

        2.Linux系统下,栈默认大小为8MB(可更改)。

(4)C语言的程序(五个区)

        ①栈

                函数调用的相关信息。

                局部变量   --- 自动申请,自动释放。

        ②堆

                空间非常大。

                手动申请,手动释放。

        ③全局区/静态区

                放全局变量,静态变量   ---默认初始化为0。

        ④字符串常量区

                存放字符串常量。

        ⑤代码区

                机器指令。

三、递归

(1)递归注解

①本质上是个循环。

②这种循环 一定会结束,因为栈的空间有限。

③递加的效率并不高,因为有些问题的解决,使用递归将变得很简单。

④倒着看问题。

(2)递归解决问题

        ①递归关系

                问题n和问题n-1之间的递推关系

        ②递归的基本形式

        返回值类型 递归函数(形参)

        {

                if(是否到达结束条件)

        {

                return 表达式//是,回归

        }else

        {

                return 问题n和n-1的递推结果//假,递推

        }

        }

四、数组作为函数参数

(1)数组元素做形参

        数组元素做形参和常量没有区别

        整个数组作为函数参数从类型角度:

        eg:printfArray(int a[10])

             printfArray(int *a)

//编译器的理解 --- int *a//指针类型 ---需要的是一个地址

//从值的角度 --- 数组名代表首元素的地址,因为数组的特点:连续性,有序性,单一性。

(2)写法

        ①形参

                printArray(int a[10],int len);//可以写成这个形式 ---提高可读性

                printArray(int *a,int len);//编译器实际理解的形式

        ②实参   ---数组名 数组长度

                printfArray(a,len);

五、心得体会

        函数设计让我体会到“边界即质量”。以前随手写大段 main,现在遵循“单一职责 + 高内聚低耦合”,把“读数据、处理数据、输出结果”拆成独立函数;形参代替全局变量,既避免副作用,又便于单元测试。尤其把数组名当指针传递后,我真正理解了“地址 + 长度”这对黄金搭档:数组连续存放的本质让 int *a 与 int a[] 等价,而长度参数则补足了指针丢失的维度信息。
        递归让我第一次“看见栈”。当 factorial(n) 层层压栈,再层层弹栈返回时,我意识到栈不仅是内存空间,更是“状态保存与回滚”的自动化机制。递归写法简洁,却因函数调用开销和栈深度限制,并不总是最优解;把递归改循环或尾递归优化,是性能与可读性的平衡艺术。
        内存五区模型让我对“变量生命周期”有了全景视角:
                栈区:函数帧、局部变量随调用自动生成和销毁,像快递柜的临时格子;
                堆区:需要 malloc/free 手动管理,像长期租用的仓库;
                全局区、字符串常量区、代码区分别存放长期数据、只读文本和机器指令。
        理解了这些,再写 char s[5][10] 时,就能预判它全落在栈上,读写高效却容量有限;若改为动态二维数组,则需 malloc 到堆,再手动释放,避免内存泄漏。
        一句话总结:函数让代码模块化,递归让算法优雅化,数组指针让数据高效化,而内存模型则是这一切的地基。 

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐