26 C 语言函数深度解析:定义与调用、返回值要点、参数机制(值传递)、原型声明、文档注释
1 函数基础概念
1.1 引入函数的必要性
在《街霸》这类游戏中,实现出拳、出脚、跳跃等动作,每项通常需编写 50 - 80 行代码。若每次调用都重复编写这些代码,程序会变得臃肿不堪,代码可读性与维护性也会大打折扣。
为解决这一问题,可将出拳、出脚、跳跃相关的代码提取出来,用大括号 {} 包裹,并为这段代码命名。之后在需要执行这些动作的地方,通过名称调用这段代码即可。提取出的这部分代码,就是程序中的函数。游戏执行相应动作时,调用对应函数即可,此方法减少了代码重复,提升了程序整洁度与可维护性。
1.2 什么是函数
函数是可重复使用的代码块,用于执行特定任务或操作。它能够将代码逻辑组织成独立单元,进而提高代码的可读性、可维护性与重用性。
在 C 语言中,一个程序可由一个或多个源文件(扩展名为 .c)组成。每个源文件都是编译单位,可包含多个函数,这些函数间能相互调用,所以函数是 C 程序的基本构成单元。
1.3 函数的作用
- 封装功能:将完整功能封装成函数,提升代码结构化程度与复用性。
- 代码模块化:按功能将程序拆分为多个模块单元,降低程序复杂度。
- 增强可维护性:若需修改某项功能,只需调整对应函数的代码。
- 隔离细节:通过函数调用隐藏实现细节,调用方只需关注输入输出。
1.4 函数的分类
从使用角度看,C 语言中的函数可分为两类:
- 库函数(标准函数):由 C 系统提供,用户无需自行定义,可直接使用。使用库函数时,必须包含对应的头文件(#include 语句)。
- 自定义函数:为满足具体需求而自行定义的函数,需先定义后使用。
2 函数的定义与调用
2.1 函数的定义
函数定义提供了函数的具体实现代码(函数体),包含函数完成任务的所有指令。其结构如下:
返回类型 函数名(参数列表)
{函数体语句1;函数体语句2;…………………………return 返回值; // 若返回类型为 void,可省略 return
}
结构说明:
- 函数名:调用函数时使用的名称,需符合标识符规范。
- 函数体:实现函数功能的代码块。
- 参数列表(形参列表):接收调用时传递的值(实参)。
- 返回值:函数执行后返回的值,类型需与返回类型一致。无返回值时,返回类型为 void。
2.2 案例:函数定义
以下代码演示了 C 语言中函数的定义:
#include <stdio.h>// 无参数无返回值的函数
void func()
{printf("hello func\n");
}// 计算两整数差值的函数
int minus(int m, int n)
{int result = m - n; // 先计算结果return result; // 再返回结果
}// 计算两浮点数和的函数
double add(double i, double j)
{return i + j; // 也可以直接返回结果
}// 返回两整数中较大值的函数
int max(int a, int b)
{return a > b ? a : b;
}// 主函数
int main()
{return 0;
}
2.3 注意:函数不能嵌套定义
C 语言中,函数是独立的,不可嵌套定义。一个函数不能定义在另一个函数内部。
int func1(int a, int b)
{ // 错误:C 语言不允许在函数内部定义另一个函数int func2(int c, int d) { // ...}
}
某些编译器扩展支持嵌套定义,但不符合 C 标准,影响可移植性,强烈不建议使用。
2.4 函数的调用
语法:通过函数名 + 圆括号 () 调用函数,参数(实参)写在括号内,多个参数用逗号分隔。
执行机制:每次调用函数时,函数体内的代码会完整执行一次,从入口到返回或结束。
#include <stdio.h>// 无参数无返回值的函数
void func()
{printf("hello func\n");
}// 计算两整数差值的函数
int minus(int m, int n)
{int result = m - n; // 先计算结果return result; // 再返回结果
}// 计算两浮点数和的函数
double add(double i, double j)
{return i + j; // 也可以直接返回结果
}// 返回两整数中较大值的函数
int max(int a, int b)
{return a > b ? a : b;
}
// 主函数
int main()
{// 调用无参函数func(); // 每次调用函数,函数体内的语句会执行一次func(); // 每次调用函数,函数体内的语句会执行一次// 调用有参函数并打印结果printf("10-20的结果:%d\n", minus(10, 20)); // -10printf("20-10的结果:%d\n", minus(20, 10)); // 10// 传递变量和字面量作为参数double d1 = 10.0, d2 = 90.0;printf("10.0+90.0的结果:%.2f\n", add(d1, d2)); // 100.00printf("20.0+80.0的结果:%.2f\n", add(20.0, 80.0)); // 100.00// 比较并打印较大值printf("66和88之间较大的是:%d\n", max(66, 88)); // 88printf("45和31之间较大的是:%d\n", max(45, 31)); // 45// 对返回值进行操作printf("max(66,88) + max(12,6) = %d\n", max(66, 88) + max(12, 6)); // 88+12=100return 0;
}
程序在 VS Code 中的运行结果如下所示:
3 函数的返回值
函数调用后可返回一个确定的值,称为返回值。返回值通常表示计算结果或函数执行状态。
3.1 无返回值类型
函数无返回值时,使用 void 作为返回类型。
正常情况
void 函数仅执行操作,不返回任何值。
#include <stdio.h>void fun01() // 无返回值函数
{printf("调用了 fun01 函数\n");
}int main()
{fun01(); // 调用无返回值函数return 0;
}
程序在 VS Code 中的运行结果如下所示:
硬要返回一个值
若尝试从 void 函数返回一个值(如通过 return 返回具体值),会导致编译错误或警告。
#include <stdio.h>void fun02() // 声明为 void 函数,但尝试返回值
{printf("调用了 fun02 函数\n");return 666; // 编译错误:void 函数不能返回值
}int main()
{fun02(); // 调用函数(编译报错)return 0;
}
程序在 VS Code 中的运行结果如下所示:
3.2 有返回值类型
正常情况
明确指定返回值类型(如 int、double),并通过 return 返回具体值。
#include <stdio.h>double fun02() // 返回 double 类型
{return 3.1415926;
}int main()
{printf("fun02() 返回的数据:%.2f\n", fun02()); // 输出 3.14return 0;
}
程序在 VS Code 中的运行结果如下所示:
无 return 语句
若函数声明了非 void 返回类型但未包含 return 语句,将返回不确定值(未定义行为)。
#include <stdio.h>int fun03() // 声明返回 int 但无 return 语句
{10 + 20; // 仅计算,未返回// return; 只有 return,没有返回值,效果和没有 return 一样
}int main()
{printf("fun03() 返回的数据(不确定值):%d\n", fun03()); // 输出不确定值return 0;
}
程序在 VS Code 中的运行结果如下所示:
返回类型不一致
若 return 表达式类型与函数声明类型不一致,编译器会尝试隐式转换(如 int → float),但需注意转换的安全性。
- 安全转换:低精度 → 高精度(如 int → double),数据无损失。
- 不安全转换:高精度 → 低精度(如 double → int),可能导致数据截断。
#include <stdio.h>int fun04() // 声明返回 int,但 return 值为 double
{return 20.89; // 隐式转换为 int,丢失小数部分
}int main()
{printf("fun04() 返回的数据(精度损失):%d\n", fun04()); // 输出 20return 0;
}
程序在 VS Code 中的运行结果如下所示:
3.3 return 语句的作用
返回值传递
若函数声明了返回类型(非 void),return 语句将函数内部的计算结果返回给调用者。
int add(int a, int b) { return a + b; // 返回两数之和
}
终止函数执行
return 语句会立即终止当前函数的执行,并跳转回调用位置。
- 无论 return 出现在函数体的何处(如循环、条件分支),后续代码均不再执行。
- 适用于提前退出函数(如错误处理或条件满足时)。
int divide(int a, int b) { if (b == 0) { return -1; // 除数为零时提前终止,返回错误码 // return; // 或者直接退出函数} return a / b; // 仅当 b != 0 时执行
}
多 return 路径
函数可通过不同条件分支包含多个 return 语句,实现灵活的控制流。
- 根据输入参数或状态选择不同的返回值或退出路径。
- 替代 if-else 嵌套,提升代码可读性。
int check_grade(int score) { if (score >= 90) return 'A'; if (score >= 80) return 'B'; if (score >= 70) return 'C'; return 'D'; // 默认路径
}
4 函数的参数
函数的参数分为形式参数(形参)和实际参数(实参)。
4.1 形参与实参
- 形参:在函数定义或声明时,函数名后括号 () 中定义的变量,函数的 “输入接口”,生命周期短暂,仅在函数内有效。
- 实参:在函数调用时,函数名后括号 () 中使用的常量、变量或表达式,外部数据的 “传递媒介”,可以是任意合法表达式。
类别 | 形参(Formal Parameter) | 实参(Actual Parameter) |
---|---|---|
定义位置 | 函数定义或声明时,括号 () 内定义的变量 | 函数调用时,括号 () 内传递的具体值(常量、变量、表达式) |
作用 | 接收外部传入的数据,作为函数内部处理的临时变量 | 提供实际数据,初始化形参的值 |
作用域 | 仅在函数体内有效(局部作用域),函数结束后销毁 | 作用域由实参本身决定(如变量实参的作用域在其定义的位置) |
存储位置 | 栈内存(函数调用时分配,结束后释放) | 取决于实参类型(如变量实参存储在原有作用域的内存中) |
4.2 参数传递 → 值传递
C 语言中,函数调用时实参的值会被复制给形参(即 “值传递”)。形参相当于一个临时变量,存储实参的值,修改形参不影响实参。
- C 语言不支持引用传递,但可通过传递地址间接实现(后续学习)。
- 若实参数量与形参数量不一致,编译器会报错。
#include <stdio.h>// 函数定义,接受两个整数参数,返回它们的和
int func(int x, int y)
{return x + y; // 返回两个整数的和
}int main()
{int sum = func(3, 5); // 调用 func 函数,实参为 3 和 5printf("func(3, 5) 返回的数为:%d\n", sum); // 输出:8// 实参与形参数量不一致时,编译报错// func(100, 299, 300); // 错误:func 函数只接受两个参数// func(100); // 错误:func 函数需要两个参数return 0;
}
程序在 VS Code 中的运行结果如下所示:
实参与形参数量必须一致,否则编译报错,如下所示:
C 语言默认采用值传递:实参的值被复制给形参,函数内对形参的修改不会影响实参。
#include <stdio.h>// 交换两个变量的值
void swap(int a, int b)
{// 注意:实参的值被复制给形参,函数内对形参的修改不会影响实参!!!int temp = a;a = b;b = temp;
}int main()
{int x = 1, y = 2;printf("交换前:x=%d, y=%d\n", x, y); // 输出:x=1, y=2swap(x, y); // 调用后 x 和 y 的值不变// 注意:实参的值被复制给形参,函数内对形参的修改不会影响实参!!!printf("交换后:x=%d, y=%d\n", x, y); // 输出:x=1, y=2return 0;
}
程序在 VS Code 中的运行结果如下所示:
5 文档注释
在 C 语言中,文档注释是一种用于生成函数或代码说明的特殊注释格式,便于开发人员理解代码功能。以下是常见的文档注释标签及其用途:
5.1 常用文档注释标签
- @brief:简要描述函数的功能。
- @param:描述函数的每个参数(格式:@param 参数名 参数说明)。
- @return:描述函数的返回值(仅用于有返回值的函数)。
- @note:补充说明函数的注意事项或其他信息。
- @warning:提示函数的使用风险或潜在问题。
5.2 工具支持
- VS Code:输入 /** 后按回车,可自动生成文档注释模板。
- Doxygen:通过解析文档注释生成代码文档(如 HTML、PDF 格式)。
5.3 案例演示
#include <stdio.h>/*** @brief 计算两个整数的和** @param x 第一个整数* @param y 第二个整数* @return 返回 x 和 y 的和* @note 此函数仅支持整数加法,不处理溢出问题*/
int func(int x, int y)
{return x + y; // 返回两个整数的和
}int main()
{int sum = func(3, 5);printf("%d\n", sum); // 输出:8return 0;
}
在 VS Code 中,将鼠标悬停在函数名上即可查看对应的文档注释,便于快速理解函数的功能、参数及返回值信息。
6 函数的原型声明
在 C 语言中,函数原型声明(Function Prototype)是编译器处理函数调用的重要依据。
6.1 函数原型的作用
提前告知编译器接口信息:函数必须 “先声明后使用”。若函数定义在 main() 或其他调用代码之后,需通过原型声明提前告知编译器函数的返回类型和参数列表,确保调用时能正确检查参数类型和返回值。
避免隐式声明风险:未声明直接调用函数时,编译器会假设返回类型为 int 并尝试猜测参数类型(C89 标准),可能导致未定义行为。函数原型可消除此类隐患。
6.2 函数原型的语法
函数原型声明需包含以下内容(不包含函数体):
- 返回类型:与函数定义一致(如 int、void)。
- 函数名:与定义完全匹配(区分大小写)。
- 参数列表:
- 必须指定参数类型(如 int、double)。
- 形参名称可选(仅用于文档说明,编译器忽略)。
// 完整形式(推荐,提升可读性)
int add(int a, int b); // 省略形参名(仅保留类型)
int add(int, int);
- 分号必需:函数原型以分号结尾,区别于函数定义。
- void 参数:若函数无参数,需显式写 void(如 int func(void);),否则可能被误认为接受任意参数(C 语言旧标准)。
6.3 案例演示
#include <stdio.h>// 函数原型声明(分号必需,形参名称可省略)
int twice1(int num1, int num2); // 完整形参名,推荐,提升可读性
int twice2(int, int, int); // 省略形参名int main(void)
{int result1 = twice1(10, 5); // 调用函数printf("twice1(10, 5) = %d\n", result1); // 输出:30int result2 = twice2(10, 5, 2); // 调用函数printf("twice2(10, 5, 2) = %d\n", result2); // 输出:34return 0;
}// 函数 twice1 的定义
/*** @brief 返回两个整数和乘以 2 的结果* @param num1 第一个整数* @param num2 第二个整数* @return 返回 int 类型*/
int twice1(int num1, int num2)
{return (num1 + num2) * 2;
}// 函数 twice2 的定义
/*** @brief 返回三个整数和乘以 2 的结果* @param num1 第一个整数* @param num2 第二个整数* @param num3 第三个整数* @return 返回 int 类型*/
int twice2(int num1, int num2, int num3)
{return (num1 + num2 + num3) * 2;
}
程序在 VS Code 中的运行结果如下所示:
相关文章:

26 C 语言函数深度解析:定义与调用、返回值要点、参数机制(值传递)、原型声明、文档注释
1 函数基础概念 1.1 引入函数的必要性 在《街霸》这类游戏中,实现出拳、出脚、跳跃等动作,每项通常需编写 50 - 80 行代码。若每次调用都重复编写这些代码,程序会变得臃肿不堪,代码可读性与维护性也会大打折扣。 为解决这一问题&…...

彻底理解一个知识点的具体步骤
文章目录 前言一、了解概念(是什么)二、理解原理(为什么)三、掌握方法(怎么用) 四、动手实践(会用)五、类比拓展(迁移能力)六、总结归纳(融会贯通…...
FFmpeg 时间戳回绕处理:保障流媒体时间连续性的核心机制
FFmpeg 时间戳回绕处理:保障流媒体时间连续性的核心机制 一、回绕处理函数 /** * Wrap a given time stamp, if there is an indication for an overflow * * param st stream // 传入一个指向AVStream结构体的指针,代表流信息 * pa…...

yolov8改进模型
YOLOv8 作为当前 YOLO 系列的最新版本,已经具备出色的性能。若要进一步改进,可以从网络架构优化、训练策略增强、多任务扩展和部署效率提升四个方向入手。以下是具体改进思路和实现示例: 1. 网络架构优化 (1) 骨干网络增强 引入 Transform…...
PostgreSQL日常运维
目录 一、PostgreSQL基础操作 1.1 登录数据库 1.2 数据库管理 1.3 数据表操作 二、数据备份与恢复 2.1 备份工具pg_dump 2.2 恢复工具pg_restore与psql 2.3 备份策略建议 三、模式(Schema) 3.1 模式的核心作用 3.2 模式操作全流程 四、远程连…...

<< C程序设计语言第2版 >> 练习 1-23 删除C语言程序中所有的注释语句
1. 前言 本篇文章介绍的是实现删除C语言源文件中所有注释的功能.希望可以给C语言初学者一点参考.代码测试并不充分, 所以肯定还有bug, 有兴趣的同学可以改进. 原题目是: 练习1-23 编写一个删除C语言程序中所有的注释语句. 要正确处理带引号的字符串与字符常量. 在C语言中, 注释…...

Fluence (FLT) 2026愿景:RWA代币化加速布局AI算力市场
2025年5月29日,苏黎世 - Fluence,企业级去中心化计算平台,荣幸地揭开其2026愿景的面纱,并宣布将于6月1日起启动四大新举措。 Fluence 成功建立、推出并商业化了其去中心化物理基础设施计算网络(DePIN)&…...

如何撰写一篇优质 Python 相关的技术文档 进阶指南
💝💝💝在 Python 项目开发与协作过程中,技术文档如同与团队沟通的桥梁,能极大提高工作效率。但想要打造一份真正实用且高质量的 Python 技术文档类教程,并非易事,需要在各个环节深入思考与精心打…...
选择if day5
5.scanf(“空白符”) 空白符作用表示匹配任意多个空白符 进入了内存缓冲区(本质就是一块内存空间) 6.scanf读取问题: a.遇到非法字符读取结束 2. %*d * 可以跳过一个字符 eg:%d%*d%d 读取第一和第三个字符…...

MiniMax V-Triune让强化学习(RL)既擅长推理也精通视觉感知
MiniMax 近日在github上分享了技术研究成果——V-Triune,这次MiniMax V-Triune的发布既是AI视觉技术也是应用工程上的一次“突围”,让强化学习(RL)既擅长推理也精通视觉感知,其实缓解了传统视觉RL“鱼和熊掌不可兼得”…...

Hash 的工程优势: port range 匹配
昨天和朋友聊到 “如何匹配一个 port range”,觉得挺有意思,简单写篇散文。 回想起十多年前,我移植并优化了 nf-HiPAC,当时还看不上 ipset hash,后来大约七八年前,我又舔 nftables,因为用它可直…...
同为.net/C#的跨平台运行时的mono和.net Core有什么区别?
Mono 和 .NET Core(现已统一为 .NET)都是 .NET 生态的跨平台实现,但它们在设计目标、技术特性和应用场景上有显著区别。以下是详细对比: 1. 历史背景 项目诞生时间开发者当前状态Mo…...
前端安全直传MinIO方案
目的:前端直接上传文件到Minio,不通过服务器中转文件。密钥不能在前端明文传输。 ## 一、架构设计 mermaid sequenceDiagram 前端->>后端: 1.请求上传凭证 后端->>MinIO: 2.生成预签名URL 后端-->>前端: 3.返回预签名URL 前端->…...

HackMyVM-Dejavu
信息搜集 主机发现 ┌──(root㉿kali)-[~] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:39:60:4c, IPv4: 192.168.43.126 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.43.1 c6:45:66:05:91:88 …...
LeetCode Hot100(动态规划)
70. 爬楼梯 题目: 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 题解: 不难发现,每一次都是从i-1或者i-2爬上来的,我们加起来求和即可 class So…...

Opencv实用操作5 图像腐蚀膨胀
相关函数 腐蚀函数 img1_erosion cv2.erode(img1,kernel,iterations1) (图片,卷积核,次数) 膨胀函数 img_dilate cv2.dilate(img2,kernel1,iterations1) (图片,卷积核,次数)…...

【赵渝强老师】OceanBase的部署架构
OceanBase数据库支持无共享(Shared-Nothing,SN)模式和共享存储(Shared-Storage,SS)模式两种部署架构。 一、 无共享(Shared-Nothing,SN)模式 在SN模式下,各…...
(18)混合云架构部署
文章目录 🚀 混合云架构部署:Java应用的云原生之旅🌩️ 混合云架构简介⚡ Java应用云原生部署五大核心技术1️⃣ 容器化与编排技术2️⃣ 服务网格与API网关3️⃣ CI/CD自动化流水线4️⃣ 多云管理平台5️⃣ 云原生Java框架与运行时 …...
c/c++的opencv霍夫变换
OpenCV中的霍夫变换 (C/C) Hough Transform 霍夫变换 (Hough Transform) 是一种在图像分析中用于检测几何形状(如直线、圆形等)的特征提取技术。它通过一种投票机制在参数空间中寻找特定形状的实例。OpenCV 库为 C 开发者提供了强大且易用的霍夫变换函数…...
AAOS系列之(七) --- AudioRecord录音逻辑分析(一)
一文讲透AAOS架构,点到为止不藏私 📌 这篇帖子给大家分析下 AudioRecord的初始化 1. 场景介绍: 在 AAOS 的 Framework 开发中,录音模块几乎是每个项目都会涉及的重要组成部分。无论是语音控制、车内对讲(同行者模式)…...
MySQL大表结构变更利器:pt-online-schema-change原理与实战指南
MySQL大表结构变更利器:pt-online-schema-change原理与实战指南 MySQL数据库运维中,最令人头疼的问题之一莫过于对大表进行结构变更(DDL操作)。传统的ALTER TABLE操作会锁表,导致业务长时间不可用,这在724小时运行的互联网业务中是不可接受的。本文将深入剖析Percona To…...

LangChain【3】之进阶内容
文章目录 说明一 LangChain Chat Model1.1 少量示例提示(Few-Shot Prompting)1.2 Few-Shot示例代码1.3 示例选择器(Eample selectors)1.4 ExampleSelector 类型1.5 ExampleSelector案例代码1.6 LangServe工具1.7 LangServe安装1.8 langchain项目结构1.9 …...

大规模JSON反序列化性能优化实战:Jackson vs FastJSON深度对比与定制化改造
背景:500KB JSON处理的性能挑战 在当今互联网复杂业务场景中,处理500KB以上的JSON数据已成为常态。 常规反序列化方案在CPU占用(超30%)和内存峰值(超原始数据3-5倍)方面表现堪忧。 本文通过Jackson与Fas…...
【OpenSearch】高性能 OpenSearch 数据导入
高性能 OpenSearch 数据导入 1.导入依赖库2.配置参数3.OpenSearch 客户端初始化4.创建索引函数5.数据生成器6.批量处理函数7.主导入函数7.1 函数定义和索引创建7.2 优化索引设置(导入前)7.3 初始化变量和打印开始信息7.4 线程池设置7.5 主数据生成和导入…...
HTML5有那些更新
语义化标签 header 头部nav 导航栏footer 底部aside 内容的侧边栏 媒体标签 audio 音频播放video 视频播放 dom查询 document.querySelector,document.querySelectorAll他们选择的对象可以是标签,也可以是类(需要加点),也可以是ID(需要加#) web存储 localStorage和sessi…...

AWS EC2 实例告警的创建与删除
在AWS云环境中,监控EC2实例的运行状态至关重要。通过CloudWatch告警,用户可以实时感知实例的CPU、网络、磁盘等关键指标异常。本文将详细介绍如何通过AWS控制台创建EC2实例告警,以及如何安全删除不再需要的告警规则,并附操作截图与…...

STM32 搭配 嵌入式SD卡在智能皮电手环中的应用全景评测
在智能皮电手环及数据存储技术不断迭代的当下,主控 MCU STM32H750 与存储 SD NAND MKDV4GIL-AST 的强强联合,正引领行业进入全新发展阶段。二者凭借低功耗、高速读写与卓越稳定性的深度融合,以及高容量低成本的突出优势,成为大规模…...

黑马点评项目01——短信登录以及登录校验的细节
1.短信登录 1.1 Session方式实现 前端点击发送验证码,后端生成验证码后,向session中存放键值对,键是"code",值是验证码;然后,后端生成sessionID以Cookie的方式发给前端,前端拿到后&a…...

【笔记】Windows 系统安装 Scoop 包管理工具
#工作记录 一、问题背景 在进行开源项目 Suna 部署过程中,执行设置向导时遭遇报错:❌ Supabase CLI is not installed. 根据资料检索,需通过 Windows 包管理工具Scoop安装 Supabase CLI。 初始尝试以管理员身份运行 PowerShell 安装 Scoop…...
LVS + Keepalived高可用群集
目录 一:keepalived双击热备基础知识 1.keepalived概述及安装 1.1keepalived的热备方式 1.2keepalived的安装与服务控制 (1)安装keepalived (2)控制keepalived服务 2.使用keepalived实现双击热备. 2.1主服务器的…...