07 · 函数与作用域

2026.09.27 · 🟡 中

函数的三个部分

int add(int a, int b);        // 1. 声明(原型):告诉编译器长啥样

int main(void) {
    int s = add(3, 5);        // 2. 调用
    return 0;
}

int add(int a, int b) {       // 3. 定义:具体实现
    return a + b;
}
  • 声明必须在调用之前出现(否则编译器不知道函数存在)。
  • 声明通常放进 .h 头文件供多文件共享(见 16-预处理器与头文件)。

⭐ C 的参数传递:一律「值传递」(理解指针的钥匙)

void badSwap(int a, int b) {   // ❌ 只改了副本,外面没变
    int t = a; a = b; b = t;
}
void goodSwap(int *a, int *b) { // ✅ 传地址,改的是原变量
    int t = *a; *a = *b; *b = t;
}

int x = 1, y = 2;
badSwap(x, y);    // x=1, y=2  没变
goodSwap(&x, &y); // x=2, y=1  成功

这是 C 最重要的一条规则:函数里想改外部变量,只能传指针。Java 里「对象传引用」的直觉在 C 里不成立。

没有函数重载

C 不支持同名不同参,同一作用域函数名必须唯一。

int add(int a, int b);
double add(double a, double b);   // ❌ 编译错误:函数名重复

作用域规则

种类 范围
局部变量 函数/代码块内
全局变量 整个文件,所有函数可见
形式参数 函数内部,是实参的副本
静态局部 函数内可见,但活得和程序一样久
  • 局部变量会遮蔽(shadow)同名的全局变量。
  • 全局变量尽量少用,多个函数乱改会让 bug 难查。

递归(见 18-递归与可变参数)

函数可以调用自己,必须有终止条件,否则栈溢出。

关联

08-数组 · 09-指针 · 18-递归与可变参数 · 04-常量与存储类