C 函数

C 函数

在 C 语言中,函数(Function) 是组织代码的基本单位。它不仅可以将程序划分为多个逻辑模块,还能提高代码的可读性、复用性和维护性。

掌握好函数的定义与使用,是编写结构清晰、高效稳定程序的关键。


一、学习目标 🎯

  1. 掌握 C 语言中函数的定义、声明与调用方法。
  2. 理解函数参数传递机制(值传递)和返回值的使用。
  3. 能够根据实际需求设计函数,并理解函数调用栈的基本原理。

二、核心重点 🔑

  1. C 中函数只能返回一个值(可以通过指针或结构体模拟多值返回)。
  2. 函数调用时参数是“值传递”,不会影响原始变量(除非使用指针)。
  3. 函数应保持单一职责原则:每个函数只做一件事。

三、详细讲解

✅ 1. 函数的定义与调用

语法:

返回类型 函数名(参数列表) {
    // 函数体
    return 返回值;
}

示例:定义一个求最大值的函数

#include <stdio.h>

// 函数定义
int max(int a, int b) {
    return (a > b) ? a : b;
}

int main(void) {
    int x = 10, y = 20;
    int result = max(x, y); // 函数调用
    printf("较大的数是:%d\n", result);
    return 0;
}

⚠️ 注意事项:

  • 函数必须先定义或声明,再调用;
  • 函数名要具有描述性;
  • main 函数是程序入口,不能被其他函数调用。

✅ 2. 函数的声明(原型)

如果函数定义在调用之后,就需要提前声明其原型。

示例:

#include <stdio.h>

// 函数声明
int add(int a, int b);

int main(void) {
    int sum = add(5, 7); // 调用尚未定义的函数
    printf("sum = %d\n", sum);
    return 0;
}

// 函数定义在后面
int add(int a, int b) {
    return a + b;
}

⚠️ 建议:

  • 将函数声明放在头文件 .h 中,便于模块化开发;
  • 使用宏防止重复包含。

✅ 3. 参数传递机制 —— 值传递(Pass by Value)

C 语言中所有参数都是“值传递”——函数接收的是变量的副本。

示例:

#include <stdio.h>

void changeValue(int x) {
    x = 100; // 只修改副本
}

int main(void) {
    int a = 10;
    changeValue(a);
    printf("a = %d\n", a); // 输出仍是 10
    return 0;
}

⚠️ 注意事项:

  • 值传递不会影响原变量;
  • 如果想改变原变量,需要使用指针(见下一章《指针》)。

✅ 4. 返回值机制

函数通过 return 语句返回一个值给调用者。

示例:

#include <stdio.h>

int square(int x) {
    return x * x;
}

int main(void) {
    int result = square(5);
    printf("5 的平方是:%d\n", result);
    return 0;
}

⚠️ 注意事项:

  • 函数可以有多个 return 语句;
  • 不建议返回局部变量的地址(会导致悬空指针);
  • 若无返回值,使用 void 类型。

✅ 5. 递归函数(Recursion)

函数可以调用自身,这种称为“递归”。

示例:计算阶乘

#include <stdio.h>

int factorial(int n) {
    if (n == 0 || n == 1) {
        return 1;
    }
    return n * factorial(n - 1);
}

int main(void) {
    int result = factorial(5);
    printf("5! = %d\n", result);
    return 0;
}

⚠️ 注意事项:

  • 必须设置终止条件;
  • 递归深度过大可能导致栈溢出;
  • 有时可用循环替代递归以提高效率。

✅ 6. 函数调用栈(Call Stack)

当你调用一个函数时,系统会为其分配一块内存空间(称为“栈帧”),用于保存参数、局部变量、返回地址等信息。

调用过程如下:

  1. 主函数调用子函数;
  2. 子函数压入调用栈;
  3. 子函数执行完毕后弹出栈;
  4. 返回结果给主函数继续执行。

⚠️ 实战建议:

  • 避免过深嵌套调用;
  • 使用调试器查看调用栈有助于理解程序流程。

四、常见陷阱与避坑指南 ⚠️

陷阱 描述 解决方案
❗未声明就调用函数 编译器无法识别 提前声明函数原型
❗函数返回局部变量地址 悬空指针 使用静态变量或动态内存分配
❗参数顺序错误 导致逻辑错误 明确命名参数含义
❗递归没有退出条件 死循环/栈溢出 设置明确的递归终止条件

五、拓展练习 🧩

🧩 练习题 1:实现一个判断素数的函数

输入一个正整数,判断是否为素数(质数)并返回布尔值。

提示:函数签名可设为 int is_prime(int n),返回 1 表示是素数,0 表示不是。


🧩 练习题 2:封装一个菜单驱动程序

编写一个函数 show_menu() 显示操作选项,并根据用户选择执行不同功能(如加法、减法等)。

要求:

  • 使用函数封装各个功能;
  • 用户可多次选择操作直到退出。

🧩 练习题 3:实现斐波那契数列函数

写一个函数 fibonacci(int n),返回第 n 项的斐波那契数。

要求:

  • 分别用递归和非递归方式实现;
  • 比较两者性能差异。

🧩 练习题 4:函数封装排序算法

编写一个函数 sort_array(int arr[], int size),对数组进行升序排序(如冒泡排序)。

要求:

  • 函数不返回新数组,直接修改原数组;
  • main 函数中测试排序效果。

六、实战建议总结

场景 推荐做法
功能复用 提取为函数,命名清晰
多个返回值 返回结构体或使用指针输出参数
模块化开发 使用 .h 文件声明函数原型
性能优化 合理使用内联函数(inline
错误处理 函数返回状态码或使用全局变量 errno

恭喜你完成了《C 函数》这一章的学习!

你现在可以熟练地将程序拆分为多个函数,写出结构清晰、易于维护的代码了!


✅ 下一章推荐学习内容(任选其一):

  • 《C 数组与字符串基础》
  • 《C 指针入门:地址、指针变量、数组访问》
  • 《C 结构体与联合体详解》
  • 《C 预处理器与宏定义》

你想继续学哪个?我来为你定制下一章 👇

posted @ 2025-06-03 20:51  红尘过客2022  阅读(30)  评论(0)    收藏  举报