26 C 语言函数深度解析:定义与调用、返回值要点、参数机制(值传递)、原型声明、文档注释

article/2025/7/24 7:54:19

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 函数原型的语法

        函数原型声明需包含以下内容(不包含函数体):

  1. 返回类型:与函数定义一致(如 int、void)。
  2. 函数名:与定义完全匹配(区分大小写)。
  3. 参数列表:
    • 必须指定参数类型(如 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 中的运行结果如下所示:


http://www.hkcw.cn/article/MWCPOJvJlM.shtml

相关文章

网易 - 灵犀办公文档

一. 企业介绍 网易是中国领先的互联网技术公司&#xff0c;为用户提供免费邮箱、游戏、搜索引擎服务&#xff0c;通过开设新闻、娱乐、体育等30多个内容频道&#xff0c;以及博客、视频、论坛等互动交流&#xff0c;网聚人的力量。 为了给中小企业和个人打造一款综合性办公产…

2025年素养大赛编程赛项练习题

我用K克网盘分享了「最新素养大赛.zip」&#xff0c;点击链接即可保存。打开「K克App」&#xff0c;无需下载在线播放视频&#xff0c;畅享原画5倍速&#xff0c;支持电视投屏。 链接&#xff1a;https://pan.quark.cn/s/c2f85a297992 提取码&#xff1a;d4Uq

CSS3前端入门(第三天)2D转换 transform

转换&#xff08;transform&#xff09;是CSS3中具有颠覆性的特征之一&#xff0c;可以根据实现元素的位移、旋转、缩放等效果 移动&#xff1a;translate旋转&#xff1a;rorate缩放&#xff1a;scale 2D转换之移动translate 2D移动是2D转换里面的一种功能&#xff0c;可以…

深兰科技董事长陈海波受邀出席2025苏商高质量发展(常州)峰会,共话AI驱动产业升级

5月29日&#xff0c;2025苏商高质量发展峰会在常州隆重开幕。本次峰会聚焦新质生产力培育与产业创新转型&#xff0c;汇聚了众多江苏省内知名企业家、专家学者及政府代表。深兰科技创始人、董事长陈海波作为人工智能领域的领军企业代表&#xff0c;受邀出席盛会并参与重要活动环…

【软件】navicat 官方免费版

Navicat Premium Lite https://www.navicat.com.cn/download/navicat-premium-lite

AIGC与影视制作:技术革命、产业重构与未来图景

文章目录 一、AIGC技术全景&#xff1a;从算法突破到产业赋能1. **技术底座&#xff1a;多模态大模型的进化路径**2. **核心算法&#xff1a;从生成对抗网络到扩散模型的迭代** 二、AIGC在影视制作全流程中的深度应用1. **剧本创作&#xff1a;从“灵感枯竭”到“创意井喷”**2…

消防体能考核器材的智能化发展

消防员体能考核器材的智能化发展&#xff0c;在实际应用中带来了诸多益处。 一、精准计时与动作评判 高精度计时 &#xff1a;如400米障碍智能考官&#xff0c;依托高精度传感器和先进算法&#xff0c;能够精确到毫秒记录跑步用时&#xff0c;改变了传统人工计时易出现误差的…

大厂前端研发岗位设计的30道Webpack面试题及解析

文章目录 一、基础核心二、配置进阶三、性能优化四、Loader原理五、Plugin机制六、高级应用七、工程化实战八、原理深挖九、异常处理十、综合场景一、基础核心 Webpack的核心概念是什么? 解析:入口(entry)、输出(output)、加载器(loader)、插件(plugins)、模式(mode)。Loader…

展会聚焦丨漫途科技亮相2025西北水务博览会!

2025第三届西北水务数字化发展论坛暨供排水节水灌溉新技术设备博览会在兰州甘肃国际会展中心圆满落幕。本届展会以“科技赋能水资源&#xff0c;数智引领新动能”为主题&#xff0c;活动汇集水务集团、科研院所、技术供应商等全产业链参与者&#xff0c;旨在通过前沿技术展示与…

二、OpenCV图像处理-图像处理

目录 1、连通性 2、形态学操作 2.1腐蚀和膨胀 2.2开闭运算 2.3礼帽和黑帽 2.4总结 3、图像平滑 3.1图像噪声 3.2均值滤波 3.3高斯滤波 3.4中值滤波 3.5总结 4、直方图 4.1直方图的原理与显示 4.2掩膜的应用 4.3直方图均衡化 4.4自适应均衡化 4.5总结 5、边缘…

代码随想录算法训练营 Day60 图论Ⅹ Bellmen_ford 系列算法

图论 题目 94. 城市间货物运输 I Bellmen_ford 队列优化算法 SPFA 大家可以发现 Bellman_ford 算法每次松弛 都是对所有边进行松弛。 但真正有效的松弛&#xff0c;是基于已经计算过的节点在做的松弛。 本图中&#xff0c;对所有边进行松弛&#xff0c;真正有效的松弛&#…

CppCon 2014 学习:Making C++ Code Beautiful

你说的完全正确&#xff0c;也很好地总结了 C 这门语言在社区中的两种典型看法&#xff1a; C 的优点&#xff08;Praise&#xff09; 优点含义Powerful允许底层控制、系统编程、高性能计算、模板元编程、并发等多种用途Fast无运行时开销&#xff0c;接近汇编级别性能&#x…

手机照片太多了存哪里?

手机相册里塞满了旅行照片、生活碎片&#xff0c;每次清理都舍不得删&#xff1f;NAS——一款超实用的存储方案&#xff0c;让你的回忆安全又有序&#xff5e; 1️⃣自动备份解放双手 手机 / 电脑 / 相机照片全自动同步到 NAS&#xff0c;再也不用手动传文件 2️⃣远程访问像…

Java String的使用续 -- StringBuilder类和StringBuffer

文章目录 字符串的不可变性StringBuilder和StringBuffer函数使用 字符串的不可变性 字符串不可变是因为有private修饰&#xff0c;只能在类的内部使用不可以在类外使用&#xff0c;因此使用时是不可以修改字符串的 public class test {public static void main(String[] args…

关于xilinx pcie ip core管脚分配出现布局布线报错问题说明

一、问题说明 xilinx的pcie几个ip core选择的物理位置是固定的&#xff0c;那么相当于管脚就被指定了&#xff0c;但是这个可能和原理图的真实情况对不上 二、xilinx官方推荐 xilinx对pcie放置的位置是有推荐的&#xff0c;如果没有按照推荐的&#xff0c;是否有问题呢&#x…

全面了解DMEM培养基:功能、组成与应用

近年来&#xff0c;研究人员陆续报道了采用营养素、生长因子和激素取代血清&#xff0c;在无血清培养基中培养各种细胞系的方法。Mather和Sato&#xff08;BBRC, 1985&#xff09;报道在含有胰岛素、转铁蛋白、表皮生长因子、黄体生成素或促卵泡激素、生长调节素和生长激素的无…

晨控CK-FR08与西门子系列PLC配置MODBUS RTU通讯连接手册

晨控CK-FR08与西门子系列PLC配置MODBUS RTU通讯连接手册 产品说明&#xff1a; CK-FR08-A01是一款基于射频识别技术的高频RFID标签读卡器&#xff0c;读卡器工作频率为13.56MHZ&#xff0c;支持对I-CODE 2、I-CODE SLI等符合ISO15693国际标准协议格式标签的读取。读卡器内部集…

基于开源链动2+1模式AI智能名片S2B2C商城小程序的企业组织生态化重构研究

摘要&#xff1a;本文以互联网时代企业组织结构变革为背景&#xff0c;探讨开源链动21模式AI智能名片S2B2C商城小程序在推动企业从封闭式向开放式生态转型中的核心作用。通过分析传统企业资源获取模式与网络化组织生态的差异&#xff0c;结合开源链动21模式的裂变机制、AI智能名…

消息队列学习总结

1.保证消息不丢失的必要条件 生产者发送消息、生产者存储消息、消费者拉取消息&#xff0c;需要保证三大流程消息不丢失&#xff0c;缺一不可。生产者保证消息完整发送并存储至broker。broker保证存储的消息不丢失。消费者保证拉取的消息一定被消费&#xff0c;即使重启了&…

Unity基础学习(十二)Unity 物理系统之范围检测

目录 一、关于范围检测的主要API&#xff1a; 1. 盒状范围检测 Physics.OverlapBox 2. 球形范围检测 Physics.OverlapSphere 3. 胶囊范围检测 Physics.OverlapCapsule 4. 盒状检测 NonAlloc 版 5. 球形检测 NonAlloc 版 6. 胶囊检测 NonAlloc 版 二、关于API中的两个重…