菜鸟的嵌入式进阶之路——函数

菜鸟的嵌入式进阶之路——函数 函数是 C 语言模块化编程的核心递归是函数调用的特殊形式预处理则是编译前的关键环节。本文结合学习笔记系统梳理函数定义与调用、递归思想与实现、数组作为函数参数、标识符作用域、存储类别关键字、预处理命令六大核心知识点附带实战作业解析帮大家吃透 C 语言进阶核心内容。一、函数模块化编程的基石1. 函数的核心价值函数将复杂问题拆解为小模块核心优势拆解问题降低编程难度模块复用减少重复代码便于调试提升项目稳定性契合单片机等嵌入式开发的模块化编程思想。2. 函数的语法结构类型标识符 函数名(形式参数) { // 函数头 // 声明部分 语句部分函数体 }组成部分核心说明类型标识符函数返回值类型数组不能作为返回值无返回值则用void函数名见名知意命名规则同变量形式参数接收外部传入数据需满足「实参 / 形参个数、类型、顺序一一对应」无需传参则用void函数体实现功能的核心代码有返回值需用return 表达式无返回值可省略return或写return;3. 函数的定义与调用定义位置写在main前兼具定义和声明作用可直接调用写在main后需在调用前声明复制函数头加;。调用方式// 1. 函数调用语句 printf(hello\n); // 2. 函数表达式 int a 2 add(1, 2); // 3. 函数作为参数 printf(sum %d\n, add(1, 2));二、递归函数的自我调用1. 递归的核心认知本质函数直接 / 间接调用自身如f1()调用f1()或f1()调用f2()、f2()调用f1()底层原理函数调用依赖栈空间先进后出Linux 默认 8M无结束条件会导致栈溢出适用场景问题可拆解为「n 与 n-1 的递推关系」如累加、阶乘、斐波那契数列。2. 递归实现的两大要素递推关系问题 n 与 n-1 的关联如sum(n) sum(n-1) n结束条件终止递归的边界如sum(1) 1。3. 递归的优缺点优点代码简洁契合某些问题的自然逻辑如汉诺塔缺点递归层次过深易栈溢出效率低于循环。三、数组作为函数参数数组作为参数时本质传递的是首元素地址而非整个数组利用数组「连续性、单一性、有序性」实现全数组访问。1. 一维数组做参数数组类型形参形式实参形式注意事项整型一维数组int a[]形式/int *a本质 长度参数数组名 实际长度sizeof(a)得到指针大小需手动传长度字符型一维数组char s[]形式/char *s本质数组名依赖\0结束无需传长度2. 二维数组做参数数组类型形参形式实参形式整型二维数组int a[][4]形式/int (*a)[4]本质 行数数组名 实际行数列数不能省略字符型二维数组char a[][10]形式/char (*a)[10]本质 行数数组名 实际行数用于批量处理多个字符串四、标识符作用域与存储类别1. 标识符的核心规则作用域标识符生效范围局部作用域{}内、全局作用域{}外可见性执行代码时能访问的标识符就近原则内层屏蔽外层生命周期变量从创建到销毁的过程。变量类型作用域生命周期存储位置局部变量局部作用域进入作用域创建离开销毁栈auto修饰默认全局变量全局作用域程序运行全程静态区 / 全局区静态局部变量static局部作用域程序运行全程静态区 / 全局区2. 核心存储关键字关键字核心作用auto修饰局部变量存储在栈默认可省略static修饰局部变量延长生命周期值继承性仅初始化一次修饰全局变量 / 函数限定作用域为本文件防止命名冲突register建议变量存入寄存器速度快不能取地址extern声明外部变量 / 函数扩展作用域五、预处理编译前的关键操作C 语言编译流程预处理 → 编译 → 汇编 → 链接预处理命令以#开头核心作用是优化编译环境。1. 宏定义#define无参宏#define PI 3.14 // 文本替换一改全改 // 示例计算圆面积 printf(面积%f\n, PI * r * r);带参宏宏函数#define MAX(a,b) ((a)(b)?(a):(b)) // 加括号避免副作用 // 调用 printf(最大值%d\n, MAX(3,5)); // 输出5宏与函数的区别宏预处理阶段文本替换无参数类型代码体积可能变大函数编译阶段处理有参数类型代码仅一份。2. 文件包含#include#include stdio.h // 系统路径查找如/usr/include #include myfunc.h // 先当前路径再系统路径作用将头文件内容替换到当前位置实现代码复用。3. 条件编译按需编译代码常用场景跨平台开发、调试代码。// 形式1判断是否定义标识符 #ifdef DEBUG printf(调试信息%d\n, a); // 定义DEBUG则编译 #else // 否则编译此处 #endif // 形式2判断表达式 #if 0 // 0表示不编译1表示编译 // 注释代码块 #endif六、核心总结1. 函数与递归函数遵循「功能单一原则」参数传递为值传递数组参数本质传地址递归需满足「递推关系 结束条件」适用于可拆解的重复性问题。2. 数组作为参数一维整型数组形参需传长度字符数组依赖\0无需传长度二维数组列数不能省略需传行数。3. 标识符与存储作用域局部{}、全局{}外可见性遵循就近原则static修饰局部变量延长生命周期修饰全局变量限定作用域。4. 预处理宏定义是文本替换带参宏需加括号避免副作用条件编译实现代码按需编译头文件需加保护防止重复包含。