18 · 递归与可变参数

2026.09.27 · 🟡 中

递归:函数调用自己

int factorial(int n) {
    if (n <= 1) return 1;        // ✅ 必须有终止条件!
    return n * factorial(n - 1);
}
  • 两个必要条件:终止条件 + 向终止条件收敛。
  • 每次调用在栈上压一帧,递归太深 → 栈溢出(Stack Overflow)。
  • 斐波那契那种会重复计算,效率差,可用记忆化或改循环。
// 经典:汉诺塔
void hanoi(int n, char a, char b, char c) {
    if (n == 1) { printf("%c -> %c\n", a, c); return; }
    hanoi(n - 1, a, c, b);
    printf("%c -> %c\n", a, c);
    hanoi(n - 1, b, a, c);
}

可变参数(... + <stdarg.h>)

#include <stdarg.h>

int sum(int count, ...) {
    va_list ap;
    va_start(ap, count);          // 从 count 之后开始取
    int s = 0;
    for (int i = 0; i < count; i++)
        s += va_arg(ap, int);     // 按 int 类型取出
    va_end(ap);                   // 必须收尾
    return s;
}

sum(3, 10, 20, 30);   // → 60
  • 你天天用的 printf(fmt, ...) 就是可变参数。
  • 必须手动知道参数个数和类型(靠第一个参数或格式串),C 不会帮你检查。

⚡ Java 对比

Java 可变参数 int... nums 有数组和长度,安全;C 的 ... 完全靠约定,取错类型 = 未定义行为。

关联

07-函数与作用域 · 09-指针 · 14-输入输出