一、什么是函数
函数是一段封装了特定功能的代码块,可以被重复调用。它接收输入(参数),经过处理后返回输出(返回值),是程序设计中实现代码复用和模块化的重要方式。
二、函数的基本结构
一个函数通常由以下几个部分组成:
- 函数名:用于标识和调用函数。
- 参数:函数接收的外部输入,可以为空。
- 函数体:实现具体功能的代码。
- 返回值:函数执行后输出的结果,可以为空。
三、函数的定义方式
在函数调用过程中,形参和实参是两个容易混淆的概念,下面结合上面的加法函数示例进行说明。
1. 形参(形式参数)
形参(形式参数)的定义:形参是函数定义时写在括号内的参数,用于接收调用方传入的值。例如上面代码中的x和y。形参在函数定义时并不占用实际内存,它只起到占位和接收调用方传入值的作用,真正被赋值是在函数被调用时。
2. 实参(实际参数)
实参(实际参数)的定义:实参是函数调用时写在括号内的参数,用于向函数传递具体的值。例如上面代码中的a和b。实参在调用时会实际占用内存,并把自身的值传递给对应的形参,供函数内部使用。
3. 两者的区别
- 定义位置不同:形参出现在函数定义中,实参出现在函数调用中。
- 内存占用不同:形参不占用内存,实参在调用时实际占用内存。
- 生命周期不同:形参随函数调用结束而销毁,实参在调用结束后仍保留。
- 传递方向不同:实参的值单向传递给形参,形参的修改不会影响实参。
下面以C语言为例,展示函数的定义方法:
创建一个自定义的加法函数
#include<stdio.h> int Add(int x, int y) //括号内的参数为形参,并不占用内存,只起到调用效果 { return x+y ; } int main() { int a = 2; int b = 3; int c = Add(a, b); //括号内的参数为实参,会实际占用内存,被Add函数调用 return 0; }四、函数的作用
使用函数可以带来以下好处:
- 代码复用:避免重复编写相同逻辑。
- 模块化:将复杂问题拆分为多个小问题。
- 易于维护:修改函数内部实现,不影响调用方。
- 提高可读性:通过函数名清晰表达代码意图。
五、库函数
库函数是指由编程语言或系统预先封装好、可以直接调用的函数。它们被集中存放在标准库或第三方库中,开发者无需重新实现底层逻辑,只需按照接口约定调用即可,从而大幅提升开发效率。
1. 库函数的分类
库函数通常可以分为以下几类:
- 标准库函数:由编程语言官方提供,随编译器或解释器一同发布,例如 C 语言中的
printf、scanf、strlen等。 - 第三方库函数:由社区或企业维护,通过包管理工具安装使用,例如 Python 中的
requests、Java 中的Apache Commons等。 - 系统调用函数:由操作系统提供,用于访问文件、网络、进程等底层资源,例如 Linux 下的
open、read、write等。
2. 库函数的优点
- 提高开发效率:直接调用现成功能,避免重复造轮子。
- 可靠性高:库函数经过大量测试和验证,稳定性更有保障。
- 可移植性好:标准库函数在不同平台上通常具有一致的接口。
- 降低维护成本:底层实现由库维护者负责,开发者只需关注业务逻辑。
3. 库函数的使用示例
下面以 C 语言为例,演示如何使用标准库函数strlen计算字符串长度:
#include<stdio.h> #include<string.h> // 引入字符串库函数头文件 int main() { char str[] = "Hello, World"; int len = strlen(str); // 调用库函数 strlen 计算长度 printf("字符串长度:%d\n", len); return 0; }通过引入string.h头文件,即可直接使用strlen函数,无需自己编写遍历字符串的代码。
4. 使用库函数的注意事项
- 引入正确的头文件:使用库函数前,必须包含对应的头文件或导入语句。
- 注意参数类型:传入的参数类型必须与函数声明一致,避免类型不匹配导致错误。
- 关注返回值:部分库函数会返回错误码或特殊值,调用后应及时检查。
- 避免命名冲突:自定义函数名不要与库函数重名,以免覆盖或引发歧义。
六、自定义 strlen 函数实现
除了直接调用库函数strlen,我们也可以自己动手实现一个功能相同的函数,从而更深入地理解字符串长度的计算原理。下面给出一个自定义的my_strlen实现:
#include<stdio.h> size_t my_strlen(char arr[], int sz) { int i = 0; int count = 0; for (i = 0; i < sz; i++) // 循环 sz 次 { if (arr[i] == '\0') break; count++; } return count; } int main() { char arr[] = "abcdef"; int sz = sizeof(arr) / sizeof(arr[0]); size_t len = my_strlen(arr, sz); printf("%zu", len); return 0; }在上面的代码中,字符串"abcdef"实际在内存中存储为:
// a b c d e f \0 // 0 1 2 3 4 5 6这里需要注意,sizeof(arr) / sizeof(arr[0])计算的是整个数组的元素个数,它会把末尾的字符串结束符\0也计算在内,因此sz的值为 7。循环遍历时,遇到\0之前的所有字符都会使count加 1,最终得到字符串长度为 6。
不过,这种实现方式存在一个明显的局限:它必须额外传入数组大小sz,使用起来不如库函数strlen方便。更常见的做法是让函数自行遍历,直到遇到\0为止,这样调用时只需传入字符串本身即可。