C语言中的函数(2)以及预处理
昨天我们学习了函数的基本知识今天我们来学习函数的传参有关的内容以及预处理阶段的内容。一、函数传参函数传参简单来说就是把数据交给函数处理C语言里主要有三种传递方式。赋值传递值传递值传递的本质是复制一份数据给形参。实参把值传给函数的形参后形参就是一个独立的副本函数内部不管怎么修改形参都不会影响外面原本的实参变量。举个例子我们在函数里修改传入的数字主函数里的原变量不会发生变化。这种传递方式适合我们只是读取外部变量的场景如果想在函数里修改外部变量的值值传递就做不到了。全局变量传参全局变量定义在所有函数外面理论上所有函数都能直接读写它不用额外传参就能实现数据共享。但全局变量能不用就尽量不用。一方面全局变量随时能被任意函数修改程序复杂之后很容易出现数据错乱排查bug难度很大而且局部变量和全局变量重名时局部变量会隐藏全局变量很容易写出bug。数组传参数组传参是我们写字符串处理、冒泡排序时最常用的方式。和普通变量不一样数组名作为参数传递时传递的不是数组的副本而是数组首元素的地址。也就是说函数内部对数组的修改会直接作用于外面的原数组。不管是整型数组还是字符型数组传参时我们一般把数组名和长度一起传入。二、递归函数递归函数就是函数内部调用自身。写递归一定要记住两个核心要点第一必须有明确的递归终止条件不然函数会无限调用直接栈溢出第二要避免过深的递归调用。就像斐波那契数列n1和n2的时候返回1这就是终止条件再把大问题拆解成n-1和n-2的子问题一层层拆解到终止条件再回溯计算结果。递归代码写起来很简洁但逻辑一定要理清楚很容易绕进去。三、预处理命令编译前的代码处理了解完函数部分我们来看预处理命令它是在代码正式编译之前执行的操作主要包含宏定义、条件编译、头文件包含这几块。宏定义宏定义一般用大写命名和普通变量做区分它本质就是简单的文本替换预处理阶段会把宏名替换成对应的内容不会做任何计算。不带参数的宏常用来定义固定的常量比如数组长度、固定数值方便后续统一修改带参宏也就是宏函数看起来和普通函数很像但它和函数有本质区别宏只是代码替换没有参数类型、返回值这些概念执行速度更快但多次使用会让代码体积变大而普通函数有完整的类型检查调用会有开销代码体积更精简。日常写代码里短小的逻辑可以用宏复杂的业务逻辑还是用普通函数更稳妥。条件编译条件编译可以让我们选择性地编译部分代码满足条件的代码加入编译不满足的直接舍弃。常用的#if、#ifdef、#ifndef这些指令在调试代码、区分不同平台版本的时候特别实用可以快速开关调试代码不用手动删除注释。头文件包含#include就是把头文件的内容展开到当前文件里标准库头文件用尖括号查找系统自带路径我们自己写的头文件用双引号优先在当前目录查找。头文件里一般存放结构体定义、函数声明、宏定义多个文件共用的函数声明放在头文件里其他文件引入头文件就能调用这也是后续多文件开发的基础。最后今天学的函数传参和预处理是C语言模块化编程的基础。值传递、数组传参的地址特性递归的终止逻辑还有宏和函数的区别都是比较重要的。