函数传参
值传递:
1.函数内部想要操作函数体外部变量值的时候需要传参
2.值传递只能使用外部变量的值而无法改变函数体外部变量值
3.函数调用,实参将值传递给形参,形参是实参的副本,形参改变不会影响实参的值
全局变量传递数据
通过使用全局变量在函数间传递数据
数组数据传递
int a[5] = {1, 2, 3, 4, 5};
int Fun(int array[], int len);
字符型数组与字符串的传递:
char str[32] = {"hello world"};
int Fun(char str[])
函数嵌套
函数的嵌套调用
函数嵌套调用指的是在一个函数内部调用另一个函数。这种调用方式允许将复杂任务分解为多个子任务,每个子任务由一个独立的函数完成,从而提高代码的可读性和模块化程度。
主调函数调用被调函数,被调函数运行结束后回到主调函数继续向下执
void functionA() {
printf("Inside functionA\\n");
}
void functionB() {
functionA(); // 嵌套调用functionA
printf("Inside functionB\\n");
}
int main() {
functionB(); // 调用functionB
return 0;
}
递归调用
递归调用的定义
递归调用是指函数或方法在定义中直接或间接调用自身的一种编程技术。通过将复杂问题分解为相似的子问题,递归能够简化代码结构,适用于具有重复性或分治性质的任务。
递归的基本要素
递归必须有一个或多个明确的终止条件,防止无限调用。例如,计算阶乘时,n=0 或 n=1 时直接返回 1。
问题需能分解为更小的同类子问题。例如,n! = n * (n-1)!。
递归的经典示例
阶乘计算
def factorial(n):
if n == 0 or n == 1: # 基线条件
return 1
else:
return n * factorial(n – 1) # 递归调用
斐波那契数列
def fibonacci(n):
if n <= 1: # 基线条件
return n
else:
return fibonacci(n – 1) + fibonacci(n – 2) # 双重递归
递归的优缺点
优点
- 代码简洁,逻辑清晰,尤其适合树形结构(如目录遍历)或数学定义(如分治算法)。
- 天然支持问题的自相似性,如快速排序、汉诺塔问题。
缺点
- 可能引发栈溢出(Stack Overflow),因每次调用都会占用栈内存。
- 重复计算问题(如斐波那契数列的朴素递归效率低)。
优化递归的方法
将递归调用置于函数末尾,某些编译器可将其转化为循环以避免栈溢出。例如:
def factorial_tail(n, accumulator=1):
if n == 0:
return accumulator
return factorial_tail(n – 1, n * accumulator) # 尾递归
缓存已计算的结果,避免重复调用。例如斐波那契数列的优化:
memo = {}
def fibonacci_memo(n):
if n in memo:
return memo[n]
if n <= 1:
return n
memo[n] = fibonacci_memo(n – 1) + fibonacci_memo(n – 2)
return memo[n]
递归与循环的选择
- 递归更适合问题天然递归的场景(如回溯、DFS)。
- 循环在性能敏感或深度较大的场景更优,可手动模拟递归的栈行为。
预处理命令 宏
不带参宏
#define PI 3.1415;
避免魔鬼数字
带参宏
与函数区别:
1.带参宏是代码的替换,没有函数调用之类的关系
2.没有传参的过程,所以效率比函数高
3.会使代码体积增大
4.函数实现比较简单的代码,使用带参宏去替代


