1. 函数初探:为什么需要函数?

各位同学,咱们今天聊聊C语言里一个绕不开的话题——函数。

说实话,我刚开始学C的时候,对函数这玩意儿挺不屑的。心想:我写个main函数不就完了吗?干嘛还要拆成那么多小函数?多麻烦啊。

直到有一次,我在一个嵌入式项目里写了800多行的main函数……嗯,那感觉,就像把整个衣柜的衣服全塞进一个行李箱。找bug找到怀疑人生。

从那以后,我彻底服了。函数不是麻烦,是救星。

1.1 为什么需要函数?

你想想看,写代码跟盖房子是一个道理。你不会把地基、墙壁、屋顶全混在一起浇筑吧?肯定是一块一块来。

函数的作用,说白了就是模块化。把一个大问题拆成若干个小问题,每个小问题用一个函数搞定。

函数的核心价值:

  • 代码复用——同一段逻辑,写一次,调N次
  • 逻辑清晰——主函数像目录,子函数像章节
  • 便于调试——哪个函数出问题,就盯着哪个查
  • 团队协作——你写你的函数,我写我的,互不干扰

我在项目中遇到过最典型的例子:一个温度采集模块,需要做滤波、转换、报警判断。如果全塞在main里,代码又臭又长。拆成 filter()convert()alarm_check() 三个函数,清爽得像刚整理过的桌面。

1.2 函数的定义与调用

函数的定义,就是告诉编译器:嘿,我这里有一块功能代码,你记好了,以后我喊名字你就跑。

基本语法长这样:

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

举个例子,写一个计算两个整数最大值的函数:

int max(int a, int b) {
    if (a > b) {
        return a;
    } else {
        return b;
    }
}

调用就更简单了:

int result = max(10, 20);  // result 就是 20

小提示:函数名最好见名知意。我见过有人给函数起名叫 f1()f2()……三个月后他自己都看不懂了。命名别偷懒,后面省大事。

1.3 第一个完整的函数示例

咱们写一个完整的程序,感受一下函数的魅力。

#include <stdio.h>

// 函数声明:告诉编译器有这个函数
void print_hello(void);

// 主函数
int main() {
    printf("程序开始运行...\n");
    
    // 调用函数
    print_hello();
    
    printf("程序结束。\n");
    return 0;
}

// 函数定义:具体实现
void print_hello(void) {
    printf("你好,函数世界!\n");
}

运行结果:

程序开始运行...
你好,函数世界!
程序结束。

你看,main函数像指挥官,print_hello 像士兵。指挥官一声令下,士兵就去干活。干完活回来,指挥官继续往下走。

注意:函数要么先声明再定义,要么把定义放在调用之前。否则编译器不认识它,会报错。我曾经因为这个被编译器骂了半小时……

1.4 函数调用的底层逻辑(简单理解)

为什么会这样?函数调用时,CPU到底干了啥?

我画了一张图,帮你理解这个过程:

main() 函数 1. 执行 printf("程序开始...") 2. 遇到 print_hello() 调用 跳转 print_hello() 函数 3. 执行函数体代码 4. 打印 "你好,函数世界!" 5. 执行完毕,返回 返回 6. 继续执行 printf("程序结束") 7. return 0,程序退出 调用者 被调用者

这张图展示了函数调用的核心流程:跳转出去,执行完再跳回来。就像你去图书馆借书——你从座位(main)走到书架(函数),拿到书再回到座位继续看。

1.5 函数分类速览

C语言的函数,大致分这么几类:

分类 说明 例子
库函数 编译器自带的,直接调用 printf()scanf()
用户自定义函数 你自己写的 max()print_hello()
有参函数 调用时传数据进去 max(10, 20)
无参函数 不需要传数据 print_hello()
有返回值函数 执行完返回一个结果 int max(...)
无返回值函数 只干活,不返回结果 void print_hello()

核心要点总结:

  • 函数是C语言的基本组成单元
  • 定义函数要写清楚:返回值类型、函数名、参数、函数体
  • 调用函数就是喊它的名字,带上需要的参数
  • 函数可以嵌套调用,但别搞太深,小心栈溢出

好了,这一章就到这里。函数这东西,你越用越觉得它香。刚开始写代码时,别怕多写几个函数。等你回头再看,你会感谢那个愿意拆函数的自己。

我的一个小习惯:每个函数只做一件事。如果一个函数干了三件事,那就拆成三个。这个原则叫"单一职责",后面讲模块化的时候还会细聊。


公众号:蓝海资料掘金营,微信 deep3321