5.1 函数、参数与返回值
函数(function)是一段可重复使用的代码,用来完成一个明确任务。你已经使用过很多库函数(library function),例如 printf()、scanf()。现在我们开始学习如何定义自己的函数。
定义函数
C 函数需要写出返回值类型、函数名、参数列表和函数体。括号里的 num1、num2 是参数(parameter),调用时传进去的 4、12 这类具体值叫实参(argument)。
int larger(int num1, int num2) {
if (num1 > num2) {
return num1;
} else {
return num2;
}
}
int main(void) {
printf("%d\n", larger(4, 12));
printf("%d\n", larger(54, 33));
return 0;
}运行结果:
12
54return 的作用是把结果交回给调用者(caller)。函数执行到 return 后,本次函数调用就结束了。
没有返回值的函数
有些函数只负责执行动作,不需要返回结果。这类函数的返回类型写成 void。
void print_board(void) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
printf(" |");
}
printf("\n");
if (i < 2) {
printf("---+---+---\n");
}
}
}运行结果:
| |
---+---+---
| |
---+---+---
| |void 函数没有有意义的返回值,可以用单独的 return; 提前结束,或者直接执行到末尾。
函数调用
函数调用(function call)发生时,程序会暂时离开当前位置,进入被调用函数的函数体(function body)内部执行。函数结束后,程序再回到原来的位置继续执行。这个“进入与返回”的过程可以用调用栈(call stack)理解。
下面的程序用函数拆分“两点间距离”的计算。
#include <stdio.h>
#include <math.h>
double square(double x) {
return x * x;
}
double distance(double x1, double y1, double x2, double y2) {
return sqrt(square(x1 - x2) + square(y1 - y2));
}
int main(void) {
printf("距离:%.1f\n", distance(0, 0, 3, 4));
return 0;
}运行结果:
距离:5.0用到 sqrt() 时需要包含 <math.h>,在部分系统上编译还要加 -lm。
参数与按值传递
参数(parameter)让函数变得灵活:相同函数接收不同实参,就能得到不同结果。C 默认按值传递(pass by value)——调用时实参的值会复制一份给形参,函数内部修改形参不会影响调用者的变量。
int square_value(int n) {
n = n * n; // 只改变副本
return n;
}
int main(void) {
int x = 5;
int y = square_value(x); // x 仍然是 5,y 是 25
printf("%d %d\n", x, y);
return 0;
}函数可以接收多个参数,但 return 只能返回一个值。把计算拆成带返回值的小函数,可以让 main 更简洁,每一步也更容易单独测试。
main 函数
C 程序总是从 main() 开始执行,它是程序的入口(entry point)。main 返回的整数会交给操作系统,0 通常表示正常结束。
int main(void) {
printf("程序开始\n");
return 0;
}