发布时间:2026/8/23 7:27:33
c语言学习--函数与指针 指针传递地址传递、引用传递值传递实参的值是非地址类型实参将自己的值的拷贝传递给形参形参与实参只有值相等是两个独立的变量。指针传递实参是地址指针变量、数组名形参接收到时地址函数内部使用形参可以修改外部的数据。#include stdio.h void fn1(int n) { n100; } void fn2(int *n) { *n100; } int main() { int num10; printf(num%d\n,num);// 10 fn1(num); printf(num%d\n,num);// 10 fn2(num); printf(num%d\n,num);// 110 return 0; }为什么调用fn1之后num的值还是10呢为什么fn2就是110呢调用fn1(num);这是值传递。main里面num 10调用 fn1 的时候把 num 里面的 10 复制一份给到 fn1 的形参变量n。⚠注意这里是复制一份fn1 里面的n是 fn1 函数自己栈上的局部变量和 main 的num是两块完全独立的内存两个盒子。调用fn2(num);num拿到 main 中 num 的内存地址把这个地址传给形参指针n。fn2 的指针变量n保存的是 main 里面 num 的地址。*n 100*解引用顺着地址直接找到 main 函数的 num 变量修改它里面的数据。main 的 num 直接变成 110。fn2 的指针变量n本身函数结束之后同样会销毁但是它已经通过地址把外面 num 的值改完了。指针函数是个函数返回指针地址注意指针函数不能返回局部变量的地址函数调用结束局部变量被销毁可以返回静态局部变量的地址。#include stdio.h #include string.h // 定义指针函数 返回两个字符串中较长的一个 char *get_longger_string(char *str1, char *str2) { return strlen(str1) strlen(str2) ? str1 : str2; } int main() { char *city Shanghai; printf(较长字符串%s \n, get_longger_string(city, Beijingnan)); return 0; }注意#include stdio.h // 定义函数 int *get_value() { // num 是局部变量函数调用结束会被销毁 int num 250; return num; } int main() { int *ptr get_value(); printf(ptr%p \n , ptr); printf(*ptr%d \n , *ptr); return 0; }错误现象: 编译的时候这串代码是没有问题的但是函数返回局部变量地址后运行时出现内存访问错误原因num是局部变量调用完之后其中的数据会被销毁。调用完之后是能拿到地址但是拿到的地址是销毁后的地址。现代系统会检测到这种错误并将地址重置为0NULL指针如何解决呢设置为静态局部变量。静态局部变量函数调用结束不销毁static int num 250;函数指针是个指针指向一个函数#include stdio.h // 定义函数 double avg(int a, int b) { return (a b) / 2.0; } int main() { // 打印地址 printf(avg: %p \n, avg); printf(avg: %p \n, avg); printf(*avg: %p \n, *avg); return 0; }打印出来的全是地址这是为什么1.avg在 C 语言中函数名会隐式转换为函数的入口地址代表函数代码在内存中存放的起始地址。avg→拿到函数代码块的首地址。2.avg取函数的地址对函数名取地址得到的还是函数入口地址。avg和avg输出结果完全一样。普通变量num是值num是地址两者不一样。 函数特殊avg、avg得到同一个函数入口地址。3.*avg*解引用函数指针。 函数指针解引用得到的还是这个函数本身又会再次转换成函数地址。 所以*avg依然打印函数入口地址。函数指针这套规则很特殊avg、avg、*avg、**avg、***avg全部等价全都是函数入口地址 你写多少层*解引用结果不变。// 调用函数 printf(%.2lf \n, avg(10, 40)); printf(%.2lf \n, (avg)(10, 40)); printf(%.2lf \n, (*avg)(10, 40));算出来的结果都是25.00对于函数avg、avg、*avg、****avg全部是同一个函数入口地址调用的是同一个函数传入同样参数返回值完全一样#include stdio.h // 定义函数 double avg(int a, int b) { return (a b) / 2.0; } int main() { // 函数指针 --------------------------------------------- // 定义函数指针 指针函数 avg 一下三种写法都一样 // double (*ptr)(int, int) avg; // double (*ptr)(int, int) *avg; double (*ptr)(int, int) avg; // 打印 printf(ptr: %p \n, ptr); printf(*ptr: %p \n, *ptr); printf(ptr: %p \n, ptr); // 使用函数指针调用avg printf(%.2lf \n, (*ptr)(70, 40)); printf(%.2lf \n, ptr(70, 40)); // printf(%.2lf \n, (ptr)(70, 40));// 这个不行因为这个是指针自己的地址 return 0; }为什么打印printf(ptr: %p \n, ptr);结果跟前面两个不一样呢因为指针ptr存放的值是函数的地址但是指针有他自己的地址所以取址后得到的是ptr自己的地址。总而言之有了函数的地址就可以调用函数总结函数的代码存放于内存的代码区调用函数的本质就是使用函数代码的地址去调用函数名、函数名、*函数名 都可以获取到函数代码的地址都可以调用函数。回调函数函数指针可以作为某个函数的参数来使用的简单来讲回调函数就是一个通过函数指针调用的函数。就是当参数的才是回调函数。回调函数作为另一个函数的参数在另一个函数的内部可以调用回调函数。// 函数指针声明格式返回值类型 (*指针名)(参数列表);#include stdio.h #include math.h // 定义函数, 需要接收一个函数作为参数 // cb 的类型是 void (*)(), 是个指针指向 void () 类型的数据 void A(void (*cb)()) { // 调用cb指向的函数 cb(); } void fn1() { printf(hello fn1); } // 定义函数实现对数组进行初始化赋值需要接收一个函数作为参数 void initarray(double *arr, int len, double (*cb)(double)) { for (int i 0; i len; i) { arr[i] cb((double)i); } } void fn2() { printf(hello fn2); } // 定义 initArray 的回调函数 double half(double n) { return n / 2; } int main() { A(fn1); printf(\n); double nums[6]; initarray(nums, 6, half); for (int i 0; i 6; i) { printf(%.2lf\n, nums[i]); } printf(\n); initarray(nums, 6, sqrt); for (int i 0; i 6; i) { printf(%.2lf , nums[i]); } printf(\n); initarray(nums, 6, cbrt); for (int i 0; i 6; i) { printf(%.2lf , nums[i]); } printf(\n); return 0; }A(fn1);fn1函数名转换为函数入口地址赋值给形参函数指针cb 在A函数内部执行cb()等价执行fn1()。initarray(nums,6,half);把half函数地址传给形参double (*cb)(double) 循环中arr[i] cb((double)i);实际调用half(i)把返回值赋值给数组。库函数也可以作为回调回调函数思想回调的核心思想框架函数只负责流程把具体业务逻辑交给外部传入的回调函数。 例子initarray只负责循环遍历数组框架生成什么数字交给回调函数half/sqrt/cbrt业务逻辑。 后续想要新的数组赋值规则只需要写新回调函数不用修改initarray内部代码。嵌入式开发中大量使用回调按键中断回调、定时器回调框架触发条件到了自动调用我们写好的回调函数。

相关新闻

2026/8/23 7:27:33

一杯奶茶钱,让五个专业设计师帮我做电商主图

我把一个20W的USB充电器插头放在桌上,拍了两张照片,传进了我们平台的AI电商推广。 想看看这支分了五个角色的团队,怎么对付一个没什么设计预算、也没电商经验的新手卖家。 结果有点出乎意料。它先审计了我。 先填表,六个格 打…

2026/8/23 8:32:37

Rust + Tauri实现一棵「习惯树」:创意应用--习惯可以成参天大树

我花了两天时间,把一款钟爱的设计理念,用 Rust Tauri 实现了。坚持不必是枯燥的对勾与数字——它把每一次坚持可视化成一棵基于分形算法生成的「习惯树」,让坚持本身成为一种值得期待的小仪式。 这篇文章聊聊为什么想做它,以及背…

2026/8/23 8:32:37

广深莞定制纸箱批量采购:综合成本与隐性物流成本核算指南

标题:广深莞定制纸箱批量采购:综合成本与隐性物流成本核算指南目标简述帮助广深莞地区工业企业全面核算定制纸箱采购的综合成本,识别显性单价之外的隐性物流、仓储、质量损耗成本,建立全周期成本评估模型,实现采购成本…

2026/8/23 8:27:37

C++模板编程:typename与class关键字的区别与应用场景详解

1. 从一次编译错误说起&#xff1a;template的两种面孔 前两天在review团队里一个实习生的代码时&#xff0c;碰到了一个挺有意思的问题。他在实现一个泛型的链表容器&#xff0c;代码大致是这样的&#xff1a; template<class T> class LinkedList { public:void inse…

2026/8/23 0:02:04

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态&#xff0c;宏观上观察到的光是由无数个微观的光量子组成的&#xff0c;每个光子在产生的瞬间&#xff0c;其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前&#xff0c;在微观层面&#xff0c;每个光量子的运动轨迹是以波函数所展现…

2026/8/23 0:02:04

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”&#xff0c;而是SIP会话的动态重定向你有没有遇到过这样的场景&#xff1a;客服坐席A正在和客户通电话&#xff0c;突然需要把这通对话无缝转给专家坐席B&#xff0c;客户完全感知不到中间的断连——既没听到忙音&#xff0c;也没被要求重新拨号…

2026/8/23 0:02:04

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack&#xff1f;如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法&#xff0c;那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/23 0:02:04

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态&#xff0c;宏观上观察到的光是由无数个微观的光量子组成的&#xff0c;每个光子在产生的瞬间&#xff0c;其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前&#xff0c;在微观层面&#xff0c;每个光量子的运动轨迹是以波函数所展现…

2026/8/23 0:02:04

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”&#xff0c;而是SIP会话的动态重定向你有没有遇到过这样的场景&#xff1a;客服坐席A正在和客户通电话&#xff0c;突然需要把这通对话无缝转给专家坐席B&#xff0c;客户完全感知不到中间的断连——既没听到忙音&#xff0c;也没被要求重新拨号…

2026/8/23 0:02:04

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack&#xff1f;如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法&#xff0c;那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/21 15:40:01

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站&#xff0c;核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测&#xff0c;千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队&#xff0c;覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/23 6:14:43

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站&#xff0c;核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测&#xff0c;千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队&#xff0c;覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/23 4:22:01

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具&#xff0c;覆盖选题构思、文献整理、内容生成、格式排版等核心场景&#xff0c;真正帮你高效搞定论文难题。 一、全流程王者&#xff1a;一站式搞定论文全链路&#xff08;一天定稿首…