C语言(12)——进阶函数
Hi!冒险者😎,欢迎闯入 C 语言的奇幻异世界🌌!
我是 ankleless🧑💻,和你一样的闯荡者~ 这是我的冒险笔记打怪升级之路——C语言之路📖,里面有踩过的坑🕳、攒的技能🌟、遇的惊喜🌈,希望能帮你少走弯路✨。
愿我们在代码山峦⛰各自攀登,顶峰碰拳👊,共赏风景呀!🥳
1. 函数的概念
在数学中,我们了解的简单的函数如: y = ax + b,其中a和 b是常数,对于任意给定的一个x,都有唯一的一个y与之对应,函数具有一一对应的特性。
同样地,我们在C语言中也引入了函数的概念,有些翻译为:子程序(程序块),子程序这种翻译更加准确一些,C语言中的函数就是一个完成特定功能的一小段代码。这段代码是有着特殊的写法和调用方法的。
C语言的程序其实是由无数个小的函数组合而成的,也可以说:一个大的计算任务可以分解成若干个小的函数(对应较小的任务)完成,同时一个函数如果能完成某项特定任务的话,这个函数也可以是复用的(重复使用),提升了开发软件的效率。
在C语言中我们一般会用到两种函数:库函数,自定义函数
2. 库函数
2.1 库函数的概念
一些常见的库函数可以在下方 博客中查询学习,遇见没有的函数可以私信博主~
C语言(02)——标准库函数大全(持续更新)_c语言库函数大全-CSDN博客
C语言中规定了C语言的各种语法规则,C语言并不提供库函数;C语言的国际标准ANSI C规定了一些常用的函数的标准,被称为标准库,那不同的编译器厂商根据ANSI提供的C语言标准就给出了一系列函数的实现。这些函数称之为库函数。
我们可以在后续的网址中学习不同的库函数:cplusplus.com - The C++ Resources Network
2.2 库函数的使用方法
对库函数的了解和认识一般包含以下几个方面:
函数的返回值
函数名
函数的参数类型
函数的功能
函数的示例
我们不妨以fgets函数为例(下图是他在C++reference中的表现形式):
从上述图片中我们可以知道fgets为函数名,char *为他的返回值,char * str、int num,和file * stream均为他的参数,由参数类型和名称构成。
他的作用是:从流中读取字符串,将他们存储在输入的指针char*中,他的读取停止有三种情况:
读取num - 1个字符元素时;遇到换行符时;遇到了文件末尾EOF(此时返回NULL)
3. 自定义函数
自定义函数是C语言中重要的一个功能,他使得程序员可以发挥他们的主观能动性,因此这个模块的学习是十分重要的。
3.1 函数的声明和定义
简单说:
- 声明:告诉编译器 “我有这个函数,别报错”,像留个 “功能预告”;
- 定义:真正把函数的 “干活逻辑” 写出来,是函数的 “实体内容”。
其实自定义函数的表现形式和库函数是一样的,如下:
ret_type fun_name(形式参数)
{
}
ret_type 是函数返回类型
fun_name 是函数名
括号中放的是形式参数
{}括起来的是函数体
┌───────────────┐
│ 函数声明 │──→ 告诉编译器:有 Add 函数,参数、返回值是啥
└───────────────┘↓
┌───────────────┐
│ main 函数 │──→ 调用 Add(3,5),找定义好的逻辑
└───────────────┘↓
┌───────────────┐
│ 函数定义 │──→ 真正计算 3+5,返回结果
└───────────────┘
为啥需要声明?
如果函数定义写在 main
后面,编译器执行 main
时,会 “看不到” 函数逻辑,直接报错。声明就是提前 “打招呼”,让编译器放心
3.2 形参(形式参数)
简单说:函数定义 / 声明里,括号里的参数是 “形参”,相当于 “占位符”。调用函数时,才会用实际的值替换它。
代码示例:
// Add 里的 a、b 就是形参,定义时只是占位
int Add(int a, int b) { return a + b;
}int main() {// 调用时,3 替换 a,5 替换 b,这时候才有实际值int result = Add(3, 5); return 0;
}
一句话总结:形参是 “函数里的变量占位”,调用时才会被实参(实际的值) 填充,形参实际上是实参内容的copy
3.3 实参(实际参数)
简单说:调用函数时,传给函数的具体值,就是实参。实参会 “填充” 到形参里,让函数干活。
代码示例:
int Add(int a, int b) { // a、b 是形参(占位)return a + b;
}int main() {// 3 和 5 是实参,调用时传给 Add 函数int result = Add(3, 5); printf("结果:%d\n", result);return 0;
}
对比理解:
- 形参:函数里的 “变量名”(定义时用,占位用)
- 实参:调用时的 “具体值”(传给函数,让形参有实际内容)
4. 函数的相关使用
学会定义函数后,还要掌握这些 “技巧”,让函数用得更灵活
4.1 return语句
作用:
- 给函数 “返回一个结果”(比如
Add
返回a + b
); - 提前结束函数(遇到
return
,函数直接停止,回到调用处)。
代码示例 1(返回结果):
int Add(int a, int b) {// 返回 a + b 的结果,函数结束return a + b;
}
代码示例 2(提前结束函数):
void PrintInfo(int age) {if (age < 0) {// 年龄不合法,直接结束函数,不执行下面的 printfreturn; }printf("年龄:%d\n", age);
}int main() {PrintInfo(-5); // 不会打印,直接 return 了PrintInfo(18); // 打印:年龄:18return 0;
}
注意:
void
类型的函数(返回void
),可以写return;
(不加值),用来提前结束函数;- 非
void
类型(比如int
、char
),return
后面必须跟对应类型的值
4.2 static函数(静态函数)
作用:用 static
修饰函数,让函数 “只能在当前文件里用”,其他文件看不到、不能调用。
代码示例(文件:test.c):
// 静态函数,只能在 test.c 里用
static int Add(int a, int b) { return a + b;
}int main() {// 可以调用(在同一个文件)int result = Add(3, 5); return 0;
}
如果其他文件(比如 main.c)想调用:
// main.c 里尝试调用 test.c 的 static 函数
int main() {// 报错!Add 是 static,只能在 test.c 里用Add(3, 5); return 0;
}
啥时候用?
想让函数 “私有”(只在当前文件干活,不暴露给其他文件),就用 static
,避免函数名冲突
4.3 extern函数(外部函数)
作用:用 extern
可以 “跨文件调用函数”,告诉编译器:“这个函数在其他文件里定义,你别报错”。
场景:项目分多个文件,函数写在 A 文件,想在 B 文件用。
代码示例(分两个文件):
- 文件:func.c(定义函数)
// 定义 Add 函数 int Add(int a, int b) { return a + b; }
- 文件:main.c(调用函数)
// 告诉编译器:Add 函数在其他文件定义(extern 可省略,默认支持跨文件找) extern int Add(int a, int b); int main() {// 调用 func.c 里的 Add 函数int result = Add(3, 5); printf("结果:%d\n", result);return 0; }
注意:
- C 语言里,函数默认就是 “extern 类型”(跨文件可见),所以
extern
经常可以省略; - 用
extern
是明确告诉编译器 “去其他文件找函数”,让代码更清晰
总结
知识点 | 核心作用 | 简单示例 |
---|---|---|
函数声明 + 定义 | 声明 “预告”,定义 “实现逻辑” | int Add(int a, int b); + 函数体 |
形参 | 函数里的 “占位变量”,调用时被实参填充 | Add(int a, int b) 里的 a、b |
实参 | 调用函数时的 “具体值”,传给形参 | Add(3, 5) 里的 3、5 |
return 语句 | 返回结果、提前结束函数 | return a + b; 或 return; |
static 函数 | 函数 “私有化”,只能在当前文件用 | static int Add(...) |
extern 函数 | 跨文件调用函数(默认也支持,写 extern 更清晰) | extern int Add(...) |