完整且详细的C语言教程,从入门到精通(5.1)--C语言函数
你们好我是一名嵌入式工程师。我正在持续更新《嵌入式工程师的C语言实战》系列教程目前已更新6篇。如果你也在学习嵌入式欢迎点个关注我们一起从零到一。文章目录前言一、什么是函数函数的作用二、函数的定义语法示例各部分详解三、函数的声明原型语法示例声明与定义的区别四、函数的调用调用方式示例五、函数的参数传递1. 值传递基本类型2. 指针传递模拟引用传递3. 数组作为参数六、函数的返回值1. 返回基本类型2. 返回指针3. 返回结构体注意4. void 函数无返回值七、函数与变量的作用域1. 局部变量2. 全局变量3. static 局部变量八、递归函数示例计算阶乘递归的注意点九、inline 函数十、函数指针进阶总结函数的要点速记完整综合示例如果这篇文章对你有帮助欢迎点赞、收藏、关注主播是一个马上粉丝量超1个的嵌入式内容主播。谢谢前言函数是C语言程序的基本构建块它让你能够将代码组织成可重用的模块。下面系统地讲解C语言函数的各个方面。一、什么是函数函数是一段封装了特定功能的代码块可以通过函数名被调用执行。它能够接收输入参数执行操作并返回一个结果返回值。函数的作用代码复用避免重复编写相同的代码。模块化将复杂程序分解为小的、可管理的部分。可读性通过有意义的函数名提高代码清晰度。可维护性修改某个功能只需修改对应的函数。二、函数的定义函数定义包括返回类型、函数名、参数列表和函数体。语法返回类型 函数名(参数类型1参数名1,参数类型2参数名2,...){// 函数体// 执行操作return返回值;// 如果返回类型不是 void必须 return}示例#includestdio.h// 定义一个函数计算两个整数的和intadd(inta,intb){intresultab;returnresult;}intmain(){intsumadd(3,5);// 调用函数printf(3 5 %d\n,sum);return0;}各部分详解部分说明示例返回类型函数返回值的类型若没有返回值则用voidint,float,void函数名标识符用于调用函数遵循命名规则add,print_message参数列表接收的输入由类型和名称组成可以为空int a, int b或void函数体花括号{}内的代码包含具体逻辑return a b;return语句结束函数执行并返回一个值void函数可以没有return 0;三、函数的声明原型函数声明也称为函数原型告诉编译器函数的存在及其签名但不提供具体实现。声明通常放在头文件中或在调用函数之前。语法返回类型 函数名(参数类型列表);示例#includestdio.h// 函数声明原型intadd(inta,intb);voidprint_hello(void);intmain(){intsumadd(10,20);// 可以在声明之后调用print_hello();return0;}// 函数定义intadd(inta,intb){returnab;}voidprint_hello(void){printf(Hello, World!\n);}声明与定义的区别对比项函数声明函数定义是否有函数体没有以分号结尾有花括号括起来的代码是否分配内存不分配分配函数代码空间位置头文件或源文件开头源文件中数量限制可以多次声明只能定义一次四、函数的调用调用方式函数名(实际参数列表);示例#includestdio.hintmax(inta,intb){return(ab)?a:b;}intmain(){intx10,y20;// 直接调用并赋值给变量intmaximummax(x,y);printf(较大值: %d\n,maximum);// 函数调用作为表达式的一部分printf(最大值是: %d\n,max(100,50));// 忽略返回值如果函数有返回值但不需要max(7,3);// 合法返回值被丢弃return0;}五、函数的参数传递C语言中参数传递是值传递pass by value——函数接收的是实参的副本修改形参不会影响实参。1. 值传递基本类型#includestdio.hvoidincrement(intn){nn1;// 修改的是形参的副本printf(函数内部: n %d\n,n);}intmain(){intx5;increment(x);printf(主函数中: x %d\n,x);// x 仍然是 5return0;}2. 指针传递模拟引用传递通过传递指针可以在函数内部修改实参的值。#includestdio.hvoidswap(int*a,int*b){inttemp*a;*a*b;*btemp;}intmain(){intx10,y20;printf(交换前: x%d, y%d\n,x,y);swap(x,y);// 传递地址printf(交换后: x%d, y%d\n,x,y);return0;}3. 数组作为参数当数组作为参数传递时实际上传递的是指向第一个元素的指针数组大小信息会丢失。#includestdio.h// 方式1直接接收指针voidprint_array(intarr[],intsize){for(inti0;isize;i){printf(%d ,arr[i]);}printf(\n);}// 方式2指针语法等价voidprint_array2(int*arr,intsize){for(inti0;isize;i){printf(%d ,*(arri));}printf(\n);}intmain(){intnumbers[]{1,2,3,4,5};intlensizeof(numbers)/sizeof(numbers[0]);print_array(numbers,len);print_array2(numbers,len);return0;}六、函数的返回值1. 返回基本类型intadd(inta,intb){returnab;}2. 返回指针#includestdio.hint*find_max(int*arr,intsize){int*max_ptrarr;for(inti1;isize;i){if(arr[i]*max_ptr){max_ptrarr[i];}}returnmax_ptr;// 返回指向数组元素的指针}intmain(){intdata[]{3,7,2,9,5};int*maxfind_max(data,5);printf(最大值: %d\n,*max);return0;}3. 返回结构体注意可以返回结构体但如果结构体很大复制开销较大通常改用指针。#includestdio.htypedefstruct{intx;inty;}Point;Pointcreate_point(intx,inty){Point p;p.xx;p.yy;returnp;// 返回结构体的副本}intmain(){Point pcreate_point(3,5);printf((%d, %d)\n,p.x,p.y);return0;}4.void函数无返回值voidgreet(constchar*name){printf(Hello, %s!\n,name);// 可以不写 return或写 return; 不带值}七、函数与变量的作用域1. 局部变量在函数内部定义的变量只在函数内可见。voidfunc(){intlocal10;// 局部变量只在 func 内可见printf(%d\n,local);}// local 在这里不可见2. 全局变量在所有函数外部定义在整个文件甚至其他文件若用extern中可见。#includestdio.hintglobal_counter0;// 全局变量voidincrement(){global_counter;// 可以在函数中访问}intmain(){increment();increment();printf(global_counter %d\n,global_counter);// 输出 2return0;}3.static局部变量在函数内用static修饰的变量其值在函数调用之间保持不变。#includestdio.hvoidcount_calls(){staticintcalls0;// 只在第一次进入时初始化calls;printf(函数被调用了 %d 次\n,calls);}intmain(){count_calls();count_calls();count_calls();return0;}八、递归函数函数可以调用自身这称为递归。示例计算阶乘#includestdio.h// 递归计算 n!intfactorial(intn){if(n1){return1;// 基准情况停止条件}returnn*factorial(n-1);// 递归调用}intmain(){printf(5! %d\n,factorial(5));// 输出 120return0;}递归的注意点必须有停止条件基准情况否则会无限递归导致栈溢出。每次递归调用都会在栈上创建新的帧深度过大可能导致栈溢出。尾递归优化某些编译器支持可以避免栈增长。九、inline函数用inline关键字建议编译器将函数代码展开在调用处避免函数调用开销。适合短小、频繁调用的函数。#includestdio.hstaticinlineintsquare(intx){returnx*x;}intmain(){intresultsquare(5);// 可能被展开为 int result 5 * 5;printf(%d\n,result);return0;}十、函数指针进阶函数指针是指向函数的指针可以作为参数传递实现回调机制。#includestdio.h// 接收函数指针作为参数intcalculate(inta,intb,int(*operation)(int,int)){returnoperation(a,b);}intadd(inta,intb){returnab;}intsub(inta,intb){returna-b;}intmul(inta,intb){returna*b;}intmain(){intx10,y5;printf(10 5 %d\n,calculate(x,y,add));printf(10 - 5 %d\n,calculate(x,y,sub));printf(10 * 5 %d\n,calculate(x,y,mul));return0;}总结函数的要点速记要点说明定义返回类型 函数名(参数列表) { 函数体 }声明返回类型 函数名(参数类型列表);返回值用return语句返回void表示无返回值参数传递值传递复制副本用指针可修改原值作用域局部变量在函数内可见全局变量在整个文件可见递归函数调用自身必须要有停止条件函数指针可指向函数用于回调或动态调用完整综合示例#includestdio.h#includestring.h// 函数声明voidprint_header(constchar*title);intmax_of_three(inta,intb,intc);voidreverse_string(char*str);int*find_max(intarr[],intsize);intmain(){// 调用 void 函数print_header(程序开始);// 调用有返回值的函数intmaxmax_of_three(10,25,18);printf(最大值: %d\n,max);// 数组操作intnumbers[]{4,7,2,9,1};int*max_ptrfind_max(numbers,5);printf(数组最大值: %d\n,*max_ptr);// 字符串操作chartext[]Hello World;reverse_string(text);printf(反转后: %s\n,text);print_header(程序结束);return0;}// 函数定义voidprint_header(constchar*title){printf( %s \n,title);}intmax_of_three(inta,intb,intc){intmaxa;if(bmax)maxb;if(cmax)maxc;returnmax;}voidreverse_string(char*str){intlenstrlen(str);for(inti0;ilen/2;i){chartempstr[i];str[i]str[len-1-i];str[len-1-i]temp;}}int*find_max(intarr[],intsize){int*maxarr[0];for(inti1;isize;i){if(arr[i]*max){maxarr[i];}}returnmax;}如果这篇文章对你有帮助欢迎点赞、收藏、关注主播是一个马上粉丝量超1个的嵌入式内容主播。谢谢

相关新闻

【大白话说Java面试题 第183题】【07_Redis篇】第19题:Redis 事务是否具有 ACID 4 个特性?

【大白话说Java面试题 第183题】【07_Redis篇】第19题:Redis 事务是否具有 ACID 4 个特性?

📌 PDF:大白话说Java面试题 — 07_Redis篇 第19题:Redis 事务是否具有 ACID 4 个特性? 📚 回答: 核心考点: Redis 事务的 ACID 特性是面试中极易踩坑的考点。大厂面试官不会满足于"不满足…

2026/7/19 15:05:05阅读更多 →
嵌入式安全启动:TI处理器X.509证书与镜像格式深度解析

嵌入式安全启动:TI处理器X.509证书与镜像格式深度解析

1. 启动镜像与X.509证书:嵌入式安全启动的基石 在嵌入式系统,尤其是工业控制、汽车电子和高端消费电子领域,设备上电后执行的 第一行代码 决定了整个系统的命运。这段代码不仅要能正确初始化硬件、加载操作系统,更肩负着抵御第一…

2026/7/19 15:05:05阅读更多 →
终极iOS自由:Downr1n开源降级工具完整指南

终极iOS自由:Downr1n开源降级工具完整指南

终极iOS自由:Downr1n开源降级工具完整指南 【免费下载链接】downr1n downgrade tethered checkm8 idevices ios 14, 15. 项目地址: https://gitcode.com/gh_mirrors/do/downr1n 你的iPhone是否因为系统升级而变得卡顿?是否怀念某个旧版本iOS的流畅…

2026/7/19 15:03:05阅读更多 →
CVPR 2023冠军方案QCNet:多智能体轨迹预测的终极指南

CVPR 2023冠军方案QCNet:多智能体轨迹预测的终极指南

CVPR 2023冠军方案QCNet:多智能体轨迹预测的终极指南 【免费下载链接】QCNet [CVPR 2023] Query-Centric Trajectory Prediction 项目地址: https://gitcode.com/gh_mirrors/qc/QCNet 在自动驾驶和智能交通系统的快速发展中,多智能体轨迹预测技术…

2026/7/19 23:10:56阅读更多 →
2026年上海全铝家居行业消费指南暨头部源头工厂权威评测报告指南

2026年上海全铝家居行业消费指南暨头部源头工厂权威评测报告指南

执行摘要随着上海及长三角地区家居消费环保升级与耐用性需求的双重爆发,全铝家居赛道近年实现跨越式增长。 数据显示2026年上海全铝家居市场规模预计突破50亿元,本地源头工厂依托全流程自营、高性价比优势迅速占领市场,头部效应持续凸显。本次…

2026/7/19 23:10:56阅读更多 →
砸百万投放却错失AI决策流量?江浙沪中小实体企业GEO破局核心力量:弱书GEO优化团队

砸百万投放却错失AI决策流量?江浙沪中小实体企业GEO破局核心力量:弱书GEO优化团队

一、行业困境:为何传统投放失灵,AI流量成新战场? 不少江浙沪的制造、本地生活品牌都面临同一个行业难题:持续投入信息流、竞价、短视频投放,但当客户使用豆包、通义千问等AI工具咨询行业选型、本地门店、产品对比问题时…

2026/7/19 23:10:56阅读更多 →
charset_normalizer常见问题解答:解决90%的编码检测难题

charset_normalizer常见问题解答:解决90%的编码检测难题

charset_normalizer常见问题解答:解决90%的编码检测难题 【免费下载链接】charset_normalizer Truly universal encoding detector in pure Python. 项目地址: https://gitcode.com/gh_mirrors/ch/charset_normalizer charset_normalizer是Python中最强大的字…

2026/7/19 23:10:56阅读更多 →
Spy Extension权限清单:它究竟能访问你多少隐私?

Spy Extension权限清单:它究竟能访问你多少隐私?

Spy Extension权限清单:它究竟能访问你多少隐私? 【免费下载链接】spy-extension A Chrome extension that will steal literally everything it can 项目地址: https://gitcode.com/gh_mirrors/sp/spy-extension Spy Extension是一款具有高度侵入…

2026/7/19 23:10:56阅读更多 →
grunt-contrib-copy 深度解析:5种文件复制模式与最佳实践

grunt-contrib-copy 深度解析:5种文件复制模式与最佳实践

grunt-contrib-copy 深度解析:5种文件复制模式与最佳实践 【免费下载链接】grunt-contrib-copy Copy files and folders. 项目地址: https://gitcode.com/gh_mirrors/gr/grunt-contrib-copy grunt-contrib-copy 是 Grunt 生态中一款高效的文件复制工具&#…

2026/7/19 23:08:56阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/19 0:01:04阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/19 0:01:04阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/19 0:01:04阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/19 0:01:04阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/19 0:01:04阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/19 0:01:04阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/19 22:50:49阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/19 14:50:26阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/19 18:50:36阅读更多 →