当前位置: 首页 > news >正文

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语句

作用

  1. 给函数 “返回一个结果”(比如 Add 返回 a + b);
  2. 提前结束函数(遇到 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 类型(比如 intchar),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(...)

http://www.xdnf.cn/news/1318951.html

相关文章:

  • Day3--滑动窗口与双指针--2461. 长度为 K 子数组中的最大和,1423. 可获得的最大点数,1052. 爱生气的书店老板
  • 数字货币的法律属性与监管完善路径探析
  • 实变函数中集合E的边界与其补集的边界是否相等
  • Android中使用Compose实现各种样式Dialog
  • Dify 从入门到精通(第 40/100 篇):Dify 的企业级权限管理
  • Mutually aided uncertainty
  • Windchill 11.0使用枚举类型自定义实用程序实现生命周期状态管理
  • Makefile介绍(Makefile教程)(C/C++编译构建、自动化构建工具)
  • 计算机网络 TCP、UDP 区别
  • 从需求到部署全套方案:餐饮服务许可证数据可视化分析系统的大数据技术实战
  • Bee1.17.25更新Bug,完善功能.不支持NOSQL,分库分表Sharding(2.X版有)
  • C语言网络编程TCP通信实战:客户端↔服务器双向键盘互动全流程解析
  • 模拟实现 useEffect 功能
  • 【R语言】R 语言中打印含有双引号的字符串时会出现 “\” 的原因解析
  • 基于STM32单片机智能RFID刷卡汽车位锁桩设计
  • 基于51单片机汽车自动照明灯超声波光敏远近光灯设计
  • 自由学习记录(85)
  • TensorRT-LLM.V1.1.0rc0:在无 GitHub 访问权限的服务器上编译 TensorRT-LLM 的完整实践
  • 计算机网络 TCP time_wait 状态 详解
  • Java开发MCP服务器
  • thingsboard 服务器在2核CPU、2G内存资源配置下如何调优提速,适合开发/演示
  • vue封装请求拦截器 响应拦截器
  • 计算机网络 Session 劫持 原理和防御措施
  • 给纯小白的Python操作 PDF 笔记
  • 【算法】模拟专题
  • nertctl使用了解
  • B站 韩顺平 笔记 (Day 21)
  • Windows平台Frida逆向分析环境完整搭建指南
  • 机器学习05-朴素贝叶斯算法
  • 攻防世界—unseping(反序列化)