C 语言函数详解

基于谭浩强《C 程序设计》第 7 章 - 从无返回值无参数到有返回值多参数

函数的基本概念

什么是函数?

函数是 C 程序的基本模块,用于完成特定的任务。就像一台机器,接收输入(参数),经过处理,产生输出(返回值)。

函数的四个分类

类型 1:无参数 无返回值

定义格式 void func(void)
调用方式 func();

示例:打印问候语、清屏等

类型 2:有参数 无返回值

定义格式 void func(int x)
调用方式 func(5);

示例:打印 n 次星号、设置参数等

类型 3:无参数 有返回值

定义格式 int func(void)
调用方式 int x = func();

示例:获取用户输入、生成随机数等

类型 4:有参数 有返回值

定义格式 int func(int x, int y)
调用方式 int z = func(3, 4);

示例:数学计算、数据转换等

函数的一般形式

返回值类型 函数名(参数列表) { // 函数体(声明 + 语句) return 表达式; // 如果返回值类型不是 void }
注意:谭浩强《C 程序设计》第 7 章强调,函数是 C 程序的基本单位,一个 C 程序由一个或多个函数组成,必须有且仅有一个 main 函数。

类型 1:无参数 无返回值

函数定义格式

void printHello(void) { printf("Hello, World!\n"); }

调用方式

int main() { printHello(); // 直接调用,不使用返回值 return 0; }

执行流程

1
程序执行到 printHello() 调用语句
2
程序跳转到 printHello 函数定义处
3
执行函数体内的 printf 语句
4
函数执行完毕,返回到调用点继续执行

互动演示

🖥️ 运行效果演示

> 等待执行...

完整示例代码

/* 无参数无返回值函数示例 */ #include <stdio.h> void printMenu(void) { printf("======== 菜单 ========\n"); printf("1. 开始游戏\n"); printf("2. 加载存档\n"); printf("3. 退出\n"); printf("======================\n"); } int main() { printMenu(); // 调用函数 return 0; }
关键点:这种函数不接收外部数据,也不返回结果,通常用于执行固定的操作,如打印菜单、清屏、初始化等。

类型 2:有参数 无返回值

函数定义格式

void printStars(int n) { for (int i = 0; i < n; i++) { printf("★"); } printf("\n"); }

调用方式

printStars(5); // 输出:★★★★★ printStars(10); // 输出:★★★★★★★★★★

参数传递过程

调用时的内存状态

main 函数 int num = 5;
↓ 传递值
printStars 函数 n = 5 (副本)

互动演示

⭐ 打印星号演示

> 等待执行...

📊 多个参数示例

> 等待执行...

完整示例代码

/* 有参数无返回值函数示例 */ #include <stdio.h> /* 打印 n 个星号 */ void printStars(int n) { for (int i = 0; i < n; i++) { printf("★"); } printf("\n"); } /* 打印两个数的和 */ void printSum(int a, int b) { int sum = a + b; printf("%d + %d = %d\n", a, b, sum); } /* 打印 n×m 的矩形 */ void printRectangle(int n, int m) { for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { printf("■ "); } printf("\n"); } } int main() { printf("1. 打印星号:"); printStars(5); printf("2. 打印加法结果:"); printSum(10, 20); printf("3. 打印矩形:\n"); printRectangle(3, 5); return 0; }
关键点:参数是"值传递",函数内修改参数不会影响原变量。适合执行需要外部输入但不需返回结果的操作。

类型 3:无参数 有返回值

函数定义格式

int getRandomNumber(void) { return rand() % 100 + 1; // 返回 1-100 的随机数 }

调用方式

int num = getRandomNumber(); printf("随机数:%d\n", num); // 或者直接在表达式中使用 if (getRandomNumber() > 50) { printf("大于 50!\n"); }

返回值传递过程

返回值的传递

函数执行 return 42;
↓ 返回值
调用点接收 int x = 42;

互动演示

🎲 生成随机数演示

> 等待执行...

📝 获取用户输入示例

> 等待执行...

完整示例代码

/* 无参数有返回值函数示例 */ #include <stdio.h> #include <stdlib.h> #include <time.h> /* 生成 1-100 的随机数 */ int getRandomNumber(void) { return rand() % 100 + 1; } /* 模拟获取用户输入 */ int getUserInput(void) { int value; printf("请输入一个整数:"); scanf("%d", &value); return value; } /* 获取当前年份 */ int getCurrentYear(void) { return 2024; // 简化示例 } int main() { srand(time(0)); // 初始化随机种子 printf("1. 随机数:%d\n", getRandomNumber()); printf("2. 随机数:%d\n", getRandomNumber()); printf("3. 当前年份:%d\n", getCurrentYear()); int num = getUserInput(); printf("你输入的是:%d\n", num); return 0; }
关键点:这种函数从内部或外部获取数据(如用户输入、传感器读数、随机数生成),然后返回给调用者使用。

类型 4:有参数 有返回值

函数定义格式

int add(int a, int b) { int result = a + b; return result; // 或直接 return a + b; }

调用方式

int sum = add(3, 4); // sum = 7 int product = multiply(5, 6); // product = 30 // 可以嵌套调用 int result = add(multiply(2, 3), 4); // result = 10

数据流向图

完整的数据流

调用点 add(5, 3)
↓ 传入参数
函数接收 a=5, b=3
函数处理 result = 8
↑ 返回结果
调用点接收 sum = 8

互动演示

➕ 加法计算器

> 等待执行...

🧮 多功能计算器

> 等待执行...

完整示例代码

/* 有参数有返回值函数示例 */ #include <stdio.h> /* 计算两数之和 */ int add(int a, int b) { return a + b; } /* 计算两数之差 */ int subtract(int a, int b) { return a - b; } /* 计算两数之积 */ int multiply(int a, int b) { return a * b; } /* 计算两数之商 */ float divide(float a, float b) { if (b == 0) { printf("错误:除数不能为 0!\n"); return 0; } return a / b; } /* 判断是否为素数 */ int isPrime(int n) { if (n < 2) return 0; for (int i = 2; i * i <= n; i++) { if (n % i == 0) return 0; } return 1; } int main() { int a = 10, b = 5; printf("%d + %d = %d\n", a, b, add(a, b)); printf("%d - %d = %d\n", a, b, subtract(a, b)); printf("%d × %d = %d\n", a, b, multiply(a, b)); printf("%d ÷ %d = %.2f\n", a, b, divide(a, b)); int num = 17; if (isPrime(num)) printf("%d 是素数\n", num); else printf("%d 不是素数\n", num); return 0; }
关键点:这是最常用的函数类型,实现完整的"输入→处理→输出"流程。适合各种计算、转换、判断等操作。

四种函数类型对比总结

函数类型 定义格式 调用方式 应用场景 示例
无参无返回值 void func(void) func(); 固定操作
打印菜单
初始化
printMenu()
clearScreen()
有参无返回值 void func(int n) func(5); 需要输入
不需返回
副作用操作
printStars(10)
setSize(w, h)
无参有返回值 int func(void) int x = func(); 获取数据
生成值
查询状态
getRandom()
getUserInput()
有参有返回值 int func(int a, int b) int z = func(3, 4); 计算转换
数据处理
判断逻辑
add(x, y)
isPrime(n)

选择指南

?
问 1:函数需要外部输入数据吗?
  • 是 → 需要参数
  • 否 → 不需要参数
?
问 2:函数需要返回结果给调用者吗?
  • 是 → 需要有返回值
  • 否 → 不需要返回值 (void)
根据两个问题的答案确定函数类型
  • 无参数 + 无返回值 → 类型 1
  • 有参数 + 无返回值 → 类型 2
  • 无参数 + 有返回值 → 类型 3
  • 有参数 + 有返回值 → 类型 4

关键概念回顾

形式参数 vs 实际参数

形参 定义时的参数
实参 调用时传入的值

实参的值传递给形参(值传递)

return 语句

有返回值函数 必须 return
void 函数 可省略 return

return 结束函数并返回值

函数声明

// 函数原型声明 int add(int, int); int main() { add(1, 2); } // 函数定义 int add(int a, int b) { return a + b; }

互动测试

第 1 题:以下哪个函数定义是"有参数无返回值"的类型?
A. int getValue(void) { return 10; }
B. void printValue(int x) { printf("%d", x); }
C. int add(int a, int b) { return a + b; }
D. void clear(void) { printf("Clear!"); }
第 2 题:以下函数调用哪个是正确的?
A. int x = printHello();
B. printStars(5);
C. getValue(10); // getValue 无参数
D. add(); // add 需要两个参数
第 3 题:关于参数传递,以下说法正确的是?
A. C 语言的参数是"引用传递"
B. C 语言的参数是"值传递"
C. 函数内修改参数会影响原变量
D. 参数传递不需要内存开销
第 4 题:编写一个函数,判断一个数是否为偶数,应该使用哪种类型?
A. void isEven(void)
B. void isEven(int n)
C. int isEven(int n)
D. int isEven(void)
第 5 题:以下代码的输出是什么?
void modify(int x) { x = 100; } int main() { int num = 50; modify(num); printf("%d", num); return 0; }
A. 100
B. 50
C. 0
D. 编译错误