7 、函数
一、函数定义
“代码复制”是程序不良的表现 → 包装成函数
\[ y=f(x) \]
和数学上函数类似:接受参数,返回值
| // 函数头
返回类型 函数名(参数列表) {
// 局部变量声明(可选)
// 语句块:实现函数功能
// return 返回值(如果有)
}
|
| // 函数头
void sum(int begin, int end) {
int i;
int sum = 0;
for (i = begin; i <= end; i++) {
sum += i;
}
printf("The sum of %d to %d is %d : ", begin, end, sum);
} // 函数体{}
|
调用函数
-
函数名(参数值)
-
()起到表示函数调用的作用
-
如果有参数,需要给出正确的数量和顺序
Example
| void cheer() {
printf("Cheer!");
}
int main() {
cheer(); // 注意要有()
return 0;
}
|
| int sum(int begin, int end) {
int i;
int sum = 0;
for (i = begin; i <= end; i++) {
sum += i;
}
return sum;
}
int main() {
printf("%d\n", sum(1, 10));
return 0;
}
|
1、函数返回
| //两种写法
return; // 无返回值,仅结束函数
return value; // 有返回值,同时结束函数
|
| int max(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
|
| void sayHello() {
printf("Hello!\n");
// return; 可省略
}
|
- 不能写
return 值; - 可以没有
return; - 调用时不能赋值:
Danger
如果函数声明了返回值类型(如 int),则必须使用 return 值; 返回相应类型的值!
return 0;
| 平台 | 含义 / 行为 |
| Windows | if errorlevel 1 用于判断程序是否成功 |
| Unix Bash | echo $? 输出上一个程序的返回值 |
| C Shell | echo $status 显示退出状态 |
return 0; 通常表示程序正常退出,非零值代表异常/错误退出。
2、函数原型
在 C 语言中,编译器从上往下逐行分析代码。
如果先使用函数、后定义函数,会出现“未定义函数”错误。
函数声明
| int max(int a, int b) { // 先定义
return (a > b) ? a : b;
}
int main() {
printf("The bigger one is: %d", max(10, 20)); // 后调用
return 0;
}
|
二、参数传递
1、类型不匹配
| int cheer(int i) {
printf("cheer!%d\n", i);
}
int main() {
cheer(2.4);
return 0;
}
/*
cheer 2
*/
|
- C 语言传统上容忍类型不匹配。
- 编译器通常会自动转换类型(例如 float → int),可能导致精度丢失。
- 在 C++ / Java 等语言中,这类隐式转换会直接报错或强烈警告。
2、值传递
| void swap(int a, int b); // 函数声明
int main() {
int a, b;
printf("Enter two numbers: ");
scanf("%d %d", &a, &b); // 👈 注意要加 & 取地址
swap(a, b);
printf("After swap: %d %d\n", a, b); // 实际没有交换
return 0;
}
void swap(int a, int b) {
int t = b;
b = a;
a = t;
}
|
⚠️ 为什么不能交换?
C 语言只能进行值传递(Pass by Value)。
- 实参的值会复制一份传给函数参数;
- 函数中对参数的修改不会影响原变量。
三、本地变量
- 每次函数调用时,会创建一个独立的变量空间
- 在函数内部定义的变量,称为本地变量
- 函数参数也是一种本地变量
📅 生存期(Lifetime)& 📦 作用域(Scope)
- 生存期:变量从创建到销毁的时间段
- 作用域:变量在代码中可见/可访问的范围
对于本地变量:生存期 = 作用域 = 所在的块 {}
stateDiagram-v2
state 块 {
生存期 : 变量存在于进入和退出之间
作用域 : 变量仅在此块内有效
}
Tip
- 可以定义在函数块中、语句块中,甚至随便一对
{} 中:
| {
int x = 5; // x 只在这个块内有效
}
|
| int x = 10;
void f() {
printf("%d\n", x); // 可访问
}
|
| int x = 10;
void f() {
int x = 5; // 内部x覆盖外部x
printf("%d\n", x); // 输出5
}
|
-
不能在同一个块中定义重名变量
-
本地变量不会自动初始化(值为随机)
-
参数在调用函数时自动初始化(来自实参)
四、 规范
1、无参数情况
| void f(); // ❌ 不推荐:表示“参数不确定”
void f(void); // ✅ 推荐:明确表示“无参数”
|
2、不嵌套定义
| int outer() {
int inner() { // 错误!C语言中函数不能嵌套定义
return 1;
}
return 0;
}
|
所有函数必须在全局作用域下单独定义。