加载中...
从零接触C语言(初览)-VI: 函数

从零接触C语言(初览)-VI: 函数

周三 7月 30 2025
1758 字 · 9 分钟

什么是函数

在本系列的第一篇正式文章中, 已经初次提到了一个重要的名词: “函数”

从那时起, 就频繁使用到了一个名为printf()的函数, 用来将字符串打印到终端上

之前只是简单的使用, 不知道你心中是否存在一个疑问: 为什么只调用一个printf()就能把目标字符串打印到终端上呢?

虽然我们并不了解printf()究竟是如何实现将字符串打印到终端上的

但是我们知道他一定并不是表面上看上去这一句话这么简单, 他一定执行了一系列的操作才完成的打印功能

它就像一个工具, 你给它一段文本, 它给你完成任务

但它到底是如何工作的?是谁写好了这个函数?我们是否也可以写出属于自己的类似工具?

这些问题的答案,都与函数的本质密切相关:

函数本质上,是一段具有特定功能的、可重复使用的代码块

通过定义函数, 我们可以把一组能够实现某种功能的语句封装起来, 在下次需要的时候直接调用函数, 而不必每次都重新编写同样的代码

我们频繁调用的printf(), 实际是C语言标准写好的一个函数, 这个函数内部封装了非常复杂的逻辑, 最终能够实现打印的功能

如果标准没有提供, 这个函数, 那么 每次需要使用打印的功能, 就需要重新实现一遍打印的逻辑, 这是非常繁琐且复杂的

函数, 是C语言最基本的组成单位之一, 我们也可以定义、实现自己的函数

函数的定义与使用

一个自定义函数的结构是这样的:

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

只看语法结果结构, 可能会觉得有一些抽象, 不太容易理解

下面可以写一个非常简单的 进行两个整数加法运算的函数, 来帮助理解:

C
#include <stdio.h>

// 自定义的函数
int add(int num1, int num2) {
	int num = num1 + num2;
	
	return num;
}

int main() {
    int num = add(10, 20);
    printf("num: %d\n", num);
    
    return 0;
}

编译运行这段代码:

从结果来看, num值为30, 但我们执行的是int num = add(10, 20);

结果说明, add(10, 20)确实完成了10 + 20并输出了结果30

再来看这个函数:

C
int add(int num1, int num2) {
	int num = num1 + num2;
	
	return num;
}

按照函数结构分析:

  1. 返回值类型: int

  2. 函数名: add

  3. 参数列表: int num1, int num2

  4. 函数体:

    C
    int num = num1 + num2;
    
    return num;
  5. 返回值: num

结合调用语句int num = add(10, 20);, 调用过程可以理解为以下几个步骤:

  1. 调用处: 调用函数名为add的函数
  2. 调用处: 传入第一个参数10, 第二个参数20
  3. 函数add被调用, 函数内: 接收第一个参数10存储到函数的临时变量num1, 接收第二个参数20存储到函数的临时变量num2
  4. 函数内: 执行函数体int num = num1 + num2;, 即num = 10 + 20;
  5. 函数内: 最终将num, 通过return作为返回值返回
  6. 调用处: 接收add(10, 20)的返回值, 并将此整型数据赋值给变量num

最终完成了1020的相加, 并得出了结果

函数的意义

上面实现了一个非常简单的函数add, 作用是两个整型的加法

你可能会有疑问: 这又什么意义呢?

加法运算不用函数, 直接a + b就能计算, 还特地写一个额外的函数, 有什么意义呢?

如果只是加减乘除这样的四则运算, 额外写一个函数确实没有什么意义

不过如果要实现更复杂的功能, 定义函数就非常有必要了

比如, 如果你要对1批数据进行排序: {181, 1681568, 45861, 684,1968, 4156, 84, 68, 456, 845, 684, 168, 4551}

你当然可以直接对这些数据进行排序, 此时你需要实现一遍排序的代码

C
int arr[] = {181, 1681568, 45861, 684,1968, 4156, 84, 68, 456, 845, 684, 168, 4551};

/*
 * 假设这里有对arr的排序代码, 可能有20行左右
 */

但是如果你要对10批数据进行排序, 难道还要实现10遍基本相同的逻辑吗?

C
// 第1批数据
int arr1[] = { ... };
/*
 * 实现20行针对arr1数据的排序
 */

// 第2批数据
int arr2[] = { ... };
/*
 * 实现20行针对arr2数据的排序
 */

// 第3批数据
int arr3[] = { ... };
/*
 * 实现20行针对arr3数据的排序
 */

// 第4批数据
int arr4[] = { ... };
/*
 * 实现20行针对arr4数据的排序
 */

// 第5批数据
int arr5[] = { ... };
/*
 * 实现20行针对arr5数据的排序
 */

...

如果是这样, 好像过于繁琐了, 而且, 你或许还不能保证每次处理数据的逻辑都百分百正确, 即使是逻辑相同的代码, 重复实现也可能会出现偏差或错误

此时, 函数的作用就体现出来了, 反正都是对整型数据排序, 排序的逻辑只需要封装在一个函数中, 在需要排序的时候, 调用函数将数据传入函数不就可以了吗?

而且只需要实现一遍代码逻辑, 并且不会出现因为重复实现可能出现的偏差或错误

如果将排序逻辑封装为函数, 上面的对数据的处理就可以演变为:

C
// 定义对整型数据排序的函数
void sort(数据) {
	// 函数体, 排序逻辑, 可能20行左右    
}

// 第1批数据
int arr1[] = { ... };
sort(arr1);

// 第2批数据
int arr2[] = { ... };
sort(arr2);

// 第3批数据
int arr3[] = { ... };
sort(arr3);

// 第4批数据
int arr4[] = { ... };
sort(arr4);

// 第5批数据
int arr5[] = { ... };
sort(arr5);

...

除此之外, 如果不使用函数, 以后写代码可能一个项目有上万行代码, 难道都要一次性全部在main()函数中实现吗?

这肯定是不现实的

所以, 函数是C语言中非常重要的组成部分, 它可以: 提高代码的复用性、增强代码可读性和结构清晰度、减少维护成本


Thanks for reading!

从零接触C语言(初览)-VI: 函数

周三 7月 30 2025
1758 字 · 9 分钟