包头网站建设制作医院网站站内文章收录量多少
2026/1/13 14:14:55 网站建设 项目流程
包头网站建设制作,医院网站站内文章收录量多少,做系统那个网站好,星空无限mv国产剧在 C/C 里#xff0c;“变量是地址”和“变量是数值”的区别#xff0c;本质上是#xff1a;这个变量里保存的比特位被解释成“数据本身”还是被解释成“指向某个内存位置/代码位置的地址”。二者在语义、可做的运算、以及对程序行为的影响上差别很大。 下面用最常见的场景…在 C/C 里“变量是地址”和“变量是数值”的区别本质上是这个变量里保存的比特位被解释成“数据本身”还是被解释成“指向某个内存位置/代码位置的地址”。二者在语义、可做的运算、以及对程序行为的影响上差别很大。下面用最常见的场景把它讲清楚。1) 变量存“数值”value variableintx5;x的内存单元里直接存放数值 5例如二进制0b...0101。你读x得到的就是 5。你写x 7;改的是x 自己这块内存里的内容。特点变量内容就是数据本身整数、浮点、结构体等。不需要再“跳转到别的地址”才能得到真正的数据。传参时f(x)默认是拷贝值。2) 变量存“地址”pointer / address variableintx5;int*px;p的内存单元里存放的是x 的地址例如0x2000_1000。p本身不是 5它是“指向 5 所在位置”的一个引用。*p才是访问这个地址里存放的数据也就是 5。关键p和*p完全不是一回事p地址指针值*p该地址处的数据解引用特点p里存的是一个“数”但这个数被解释为内存地址。对p做运算例如p1通常是按类型步进sizeof(*p)的地址运算。*p 7;改的不是p而是p 指向的那块内存这里就是改x。3) “函数参数是地址”和“函数参数是数值”的区别最重要A. 参数是数值函数拿到的是副本改不了外部变量voidf(inta){a10;}intx5;f(x);// x 仍然是 5a是x的拷贝。改a不影响x。B. 参数是地址指针函数可以改外部变量voidg(int*a){*a10;}intx5;g(x);// x 变成 10a保存的是x的地址地址本身也是“按值传递”进来的但这个值恰好是地址。通过*a可以修改到外部的x。结论C 语言里“传引用”通常就是“把地址当作参数传进去”。4) 函数指针变量里存的是“代码地址”你前面提到的XSpiPs_StatusHandler FunctionPtr就是典型FunctionPtr变量里存的是某个函数入口的地址代码段地址。当驱动写InstancePtr-StatusHandler FunctionPtr;就是把“要回调的函数地址”保存起来。之后调用InstancePtr-StatusHandler(...)本质是跳转到这个地址执行代码。这和CallBackRef的区别非常明确CallBackRef数据地址告诉回调“上下文对象在哪”StatusHandler代码地址告诉驱动“发生事件时执行哪段代码”5) 一句话总结数值变量保存“数据本身”读出来就能用。地址变量指针/句柄/函数指针保存“某个东西的位置”数据位置或代码位置必须通过“解引用/调用/传给 API”才能真正作用到目标。函数的变量是地址与函数变量是数值的区别可以用一个非常实用的决策框架来判断你是要“传数据本身”还是要“让对方能访问/修改某块存储或执行某段代码”。1) 用“数值”value的典型场景A. 参数只是“配置/选择/常量”不需要让函数改你的变量例如分频系数、模式位、寄存器 offset、长度、状态码ByteCount、DelayInit10、prescaler256XSpiPs_SetClkPrescaler(SpiInstance,XSPIPS_CLK_PRESCALE_256);// 分频值是数值XSpiPs_SetDelays(SpiInstance,10,10,10,10);// 延时字段是数值原因这些是命令参数函数拿到副本就够了。B. 数据很小复制成本低且你不希望被修改例如int,u32, 小的枚举。优点简单、安全、不会出现指针悬空。2) 用“地址/指针”pointer的典型场景A. 需要让函数“修改/填充”你提供的存储输出参数例如读寄存器、读数据、返回多个结果intread_reg(u32 addr,u8*val_out);原因C 只有值传递要把结果写回调用者就要传地址。B. 数据量大不想拷贝尤其是 buffer / structSPI 发送/接收 buffer 必须传指针XSpiPs_Transfer(SpiInstance,SendBufPtr,RecvBufPtr,ByteCount);原因ByteCount可能很多字节拷贝一份代价高且没必要硬件 DMA/ISR 也必须知道 buffer 在哪。C. 需要共享同一份对象状态驱动实例、设备上下文例如XSpiPs *InstancePtr驱动要在InstancePtr里更新IsBusy、指针、计数器等所以必须传地址不然改不到原来的实例3)const指针只读访问非常推荐的习惯当你传的是“地址”但你希望对方只读不改就用constintfoo(constu8*data,u32 len);// data 指向的内容不会被 foo 改例如你自己封装的spi_write_then_read(const uint8_t* txbuf, ...)就是这个思路发送缓冲不应被驱动改写。4) 句柄/指针作为CallBackRef什么时候用当你使用中断/异步机制SPI 中断完成才回调时回调函数需要知道“该操作哪一个对象/同步原语”。StatusHandler告诉驱动“发生事件时调用哪段代码”函数地址CallBackRef告诉这段代码“要操作谁”数据地址/句柄典型用法裸机传一个struct ctx指针回调里置位doneFreeRTOS传SemaphoreHandle_t/TaskHandle_t/QueueHandle_t回调里GiveFromISR或NotifyGiveFromISR什么时候用句柄当 CallBackRef你上层是“等待某个 RTOS 对象”来同步的信号量/通知/队列你希望回调尽量短、在 ISR 内只做“唤醒/通知”5) 函数指针XSpiPs_StatusHandler什么时候用当你需要把行为/策略交给用户实现驱动不能写死时就用函数指针传输完成时怎么通知打印置位发信号量出错时怎么处理重试记录报警这属于“回调/多态”机制同一套驱动可以接不同上层策略。6) 一个最实用的“选择口诀”你可以按下面 4 个问题判断我需要函数改我的变量/填我的缓冲吗需要 → 传地址指针不需要 → 传数值数据是否很大buffer/结构体很大 → 传地址避免拷贝很小 → 传数值我是在做异步/中断回调吗是 → 用函数指针回调 CallBackRef上下文否 → 可能只用普通函数返回值/输出参数对象是否需要跨函数持续保存状态driver instance是 → 传对象地址实例指针否 → 传数值即可7) 对你当前 SPI 代码的直接对照SpiInstance必须是地址驱动要改它内部状态XSPIPS_CLK_PRESCALE_256、10是数值配置参数SendBufPtr/RecvBufPtr必须是地址bufferStatusHandler函数指针代码地址CallBackRef上下文指针/句柄数据地址

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询