函数是C语言程序的基本组成单元,它允许我们将一段独立的功能代码封装起来,通过函数名进行调用。 使用函数可以避免代码重复、提高可读性、便于调试和维护,是实现模块化编程的核心手段。 本章将系统讲解函数的基本概念、定义、声明、调用、参数传递机制以及相关的注意事项。
函数是一段完成特定任务的独立代码块,它可以接收输入(参数),并可能返回一个结果(返回值)。
C语言程序由多个函数组成,其中必须有且仅有一个名为 main 的函数作为程序入口。
函数的好处包括:
函数定义包括返回类型、函数名、参数列表和函数体。语法格式:
返回类型 函数名(参数类型1 参数名1, 参数类型2 参数名2, ...) {
// 函数体
// 可以包含变量声明、语句等
return 返回值; // 如果返回类型为void,则不需要return或直接return;
}
示例:定义一个计算两个整数之和的函数。
int sum(int a, int b) {
int result = a + b;
return result;
}
如果函数不需要返回值,返回类型应为 void:
void printHello() {
printf("Hello, World!\n");
// 可以没有return,或使用 return; 提前结束
}
在使用一个函数之前,编译器需要知道它的返回类型、函数名和参数类型。如果函数的定义出现在调用之后,就需要在调用前进行函数声明(也称为函数原型)。 函数声明通常放在文件开头或头文件中。
#include <stdio.h>
// 函数声明(原型)
int sum(int a, int b);
void printMessage(void);
int main() {
int x = 10, y = 20;
int result = sum(x, y); // 调用
printf("结果: %d\n", result);
printMessage();
return 0;
}
// 函数定义
int sum(int a, int b) {
return a + b;
}
void printMessage() {
printf("这是消息函数\n");
}
调用函数时,需要提供与函数原型匹配的实参(实际参数),并使用函数返回的值(如果有)。函数调用可以出现在表达式中,也可以单独作为语句。
int main() {
int a = 5, b = 7;
int result = sum(a, b); // 调用,将结果赋给result
printf("Sum = %d\n", result);
// 直接使用函数返回值
printf("Sum = %d\n", sum(3, 4));
// 无返回值函数调用作为语句
printHello();
return 0;
}
C语言中,函数参数传递采用值传递(pass by value)方式。即实参的值被复制给形参,函数内部对形参的修改不会影响外部的实参。 这使得函数内部的变量与外部隔离,保证了数据的安全性。
#include <stdio.h>
void changeValue(int x) {
x = 100; // 修改的是形参的副本,不影响实参
printf("函数内部: x = %d\n", x);
}
int main() {
int num = 10;
printf("调用前: num = %d\n", num);
changeValue(num);
printf("调用后: num = %d\n", num); // 仍然是10
return 0;
}
函数通过 return 语句返回一个值给调用者。return 语句会立即结束函数的执行,并将控制权返回给调用处。
一个函数可以有多个 return 语句,但通常建议保持单一出口以提高可读性。
// 返回两个数中的较大者
int max(int a, int b) {
if (a > b)
return a;
else
return b;
}
// 提前返回示例
int divide(int a, int b) {
if (b == 0) {
printf("除数不能为0!\n");
return 0; // 提前返回,不继续执行
}
return a / b;
}
如果函数返回类型为 void,可以使用 return; 提前结束函数,也可以省略最后的 return。
函数内部定义的变量称为局部变量,它们的作用域仅限于函数内部,生命周期从进入函数开始到函数返回结束。
在所有函数外部定义的变量是全局变量,作用域为整个文件(如果使用 extern 还可以跨文件),生命周期贯穿整个程序运行。
#include <stdio.h>
int global = 100; // 全局变量
void func() {
int local = 10; // 局部变量
printf("局部变量: %d, 全局变量: %d\n", local, global);
// 可以修改全局变量
global++;
}
int main() {
func();
func();
printf("全局变量最终值: %d\n", global); // 102
return 0;
}
函数可以调用其他函数,甚至调用自身(递归调用)。下面是一个简单的嵌套调用示例:
#include <stdio.h>
int add(int x, int y) {
return x + y;
}
int multiply(int x, int y) {
return x * y;
}
int calculate(int a, int b, int c) {
int sum = add(a, b);
return multiply(sum, c);
}
int main() {
int result = calculate(2, 3, 4); // (2+3)*4 = 20
printf("结果: %d\n", result);
return 0;
}
递归函数是指函数在其定义中直接或间接调用自身。递归需要满足两个条件:存在基线条件(终止条件)和递归条件(向基线靠近)。 经典示例:计算阶乘。
#include <stdio.h>
// 递归计算 n!
long long factorial(int n) {
if (n <= 1) // 基线条件
return 1;
else
return n * factorial(n - 1); // 递归调用
}
int main() {
int n = 5;
printf("%d! = %lld\n", n, factorial(n));
return 0;
}
calculateSum、isPrime。errno 或输出参数。#include <stdio.h>
// 函数声明
double add(double a, double b);
double subtract(double a, double b);
double multiply(double a, double b);
double divide(double a, double b);
void showMenu();
int main() {
int choice;
double x, y, result;
do {
showMenu();
printf("请选择(1-5): ");
scanf("%d", &choice);
if (choice >= 1 && choice <= 4) {
printf("请输入两个数字: ");
scanf("%lf %lf", &x, &y);
}
switch (choice) {
case 1:
result = add(x, y);
printf("%.2f + %.2f = %.2f\n", x, y, result);
break;
case 2:
result = subtract(x, y);
printf("%.2f - %.2f = %.2f\n", x, y, result);
break;
case 3:
result = multiply(x, y);
printf("%.2f * %.2f = %.2f\n", x, y, result);
break;
case 4:
if (y == 0)
printf("除数不能为0!\n");
else {
result = divide(x, y);
printf("%.2f / %.2f = %.2f\n", x, y, result);
}
break;
case 5:
printf("退出程序\n");
break;
default:
printf("无效选择,请重新输入\n");
}
printf("\n");
} while (choice != 5);
return 0;
}
// 函数定义
void showMenu() {
printf("===== 计算器菜单 =====\n");
printf("1. 加法\n");
printf("2. 减法\n");
printf("3. 乘法\n");
printf("4. 除法\n");
printf("5. 退出\n");
printf("=====================\n");
}
double add(double a, double b) {
return a + b;
}
double subtract(double a, double b) {
return a - b;
}
double multiply(double a, double b) {
return a * b;
}
double divide(double a, double b) {
return a / b;
}
int func(),可能导致参数传递错误。C99起禁止隐式声明。函数是C语言模块化编程的基石。掌握函数的定义、声明、调用和参数传递机制后,你已经能够将程序分解为可重用的模块。 下一章我们将学习指针,这是C语言的精髓,也是实现更高级数据结构(如动态数组、链表)和高效参数传递的基础。