当前位置: 首页 > news >正文

《 一次让你学会并掌握指针》嵌入式-C语言高级-指针

好的,我们来一次把C语言指针彻底搞懂,尤其是从嵌入式开发最常用的角度去讲。

目标:看完这篇后,你能自信地说“我指针基本会了”,并且能看懂90%嵌入式C代码里的指针用法。

第一步:先把最本质的概念建立(很多人一辈子都没建立)

指针最核心的3句话(请背下来):

  1. 内存的本质是编号(从0开始的整数,通常用十六进制表示)
  2. 指针变量本质上是存地址的普通变量
  3. *是“去它指向的地址里取东西/放东西”的操作符

用最直白的比喻:

内存就像一个超级长的信箱排(0号 ~ 几亿号) int a = 100; → 找一个空信箱(比如0x20000010),把100塞进去 int *p; → 买一个记事本,专门用来记“哪个信箱有东西” p = &a; → 把a的信箱号(0x20000010)写到记事本上 *p = 200; → 根据记事本上的地址去找信箱,把里面的东西改成200 printf("%d", *p); → 根据记事本去信箱看现在里面是多少 → 输出200

第二步:最常用的5种指针类型(嵌入式最常考/最常写)

写法含义嵌入式最典型用法sizeof(这个类型)
int *p指向int的指针普通变量、数组元素、结构体成员通常4字节(32位)/8字节(64位)
uint8_t *p指向字节的指针(最常用!)操作寄存器、串口收发缓冲区、I2C/SPI数据4或8字节
const uint8_t *p只读字节指针指向常量区字符串、Flash里的查找表同上
uint8_t * const p指针本身不可改(常量指针)指向固定硬件寄存器地址同上
void *p万能指针(什么都能指)malloc、memcpy、硬件寄存器映射同上

第三步:嵌入式最经典的真实写法(强烈建议全部敲一遍)

// 1. 寄存器直接操作(最常见写法)#defineGPIOA_BASE((uint32_t)0x40020000)#defineGPIOA_ODR(*(volatileuint32_t*)(GPIOA_BASE+0x14))// 等价写法(更推荐初学者这样理解)volatileuint32_t*constGPIOA_ODR=(volatileuint32_t*)(0x40020000+0x14);voidLED_ON(void){*GPIOA_ODR|=(1U<<5);// 置位 PA5}voidLED_OFF(void){*GPIOA_ODR&=~(1U<<5);// 清零 PA5}
// 2. 内存映射 + 结构体方式(现代STM32 HAL/LL最常用)typedefstruct{volatileuint32_tMODER;// 0x00volatileuint32_tOTYPER;// 0x04// ... 很多寄存器volatileuint32_tODR;// 0x14}GPIO_TypeDef;#defineGPIOA((GPIO_TypeDef*)0x40020000)voidLED_Toggle(void){GPIOA->ODR^=(1U<<5);}
// 3. 一级指针做函数参数(最常用传出多个值的方式)voidswap(int*a,int*b){inttemp=*a;*a=*b;*b=temp;}// 用法intx=10,y=20;swap(&x,&y);// 现在 x=20, y=10
// 4. 数组名就是指针(但不能 ++/-- 也不能赋值)uint8_tbuf[100];uint8_t*p=buf;// OK,等价于 &buf[0]p++;// 指向 buf[1]*(p+3)=0x55;// 等价 buf[4] = 0x55// 但下面这些都不合法:// buf++; // 错!数组名不能自增// buf = p; // 错!数组名不能被赋值
// 5. 指针数组 vs 数组指针(面试+驱动最爱考)intarr[5];// 普通数组int*ptr_arr[5];// 指针数组:5个int* (每个元素都是指针)int(*ptr_to_arr)[5];// 数组指针:指向“5个int的数组” (很少用,但驱动里常见)// 经典写法(函数指针数组)void(*task_func[])(void)={task1,task2,task3};task_func[1]();// 执行 task2()

第四步:嵌入式最容易踩的10个坑(避开这些能少debug很多天)

  1. 野指针:定义了指针但没初始化就用*p
  2. 释放后继续使用:free() / 任务结束 / 栈空间回收后还用
  3. 忘记 volatile:寄存器/共享变量/中断标志没加 volatile
  4. 指针类型对不齐uint32_t*去指uint8_t数组 → 硬件对齐硬故障
  5. 返回局部变量地址:return &local_var; → 栈被回收,变成野指针
  6. 数组传参退化int func(int a[])其实是int func(int *a)
  7. const 位置搞错const int *pvsint * const p
  8. void强制转换前没对齐*(尤其DMA、硬件寄存器)
  9. 多级指针没搞清char **argv是指针的指针
  10. sizeof(指针) ≠ sizeof(它指向的东西)(64位系统尤其明显)

第五步:快速自测清单(做完这些说明你指针基本过关)

1.inta=10;int*p=&a;++p;现在*p 是多少?(答案:非法/未定义)2.constintx=100;constint*p=&x;*p=200;// 合法吗?3.intarr[3]={1,2,3};int(*p)[3]=&arr;现在 p+1指向哪里?4.voidfunc(constuint8_t*buf,uint16_tlen);为什么 buf 用const5.volatileuint32_t*constREG=(uint32_t*)0x40000000;两个const分别限制什么?6.char*str="hello";str[0]='H';// 会发生什么?(嵌入式尤其危险)7.如何定义一个指向“函数的指针”,函数原型是voiddelay_ms(uint32_tms)8.二维数组intmat[4][5];如何用指针遍历它?(两种常用写法)

答案可以自己先写出来,再对照网上或书验证。

如果你把上面内容全部理解 + 代码都敲一遍,恭喜你——嵌入式C里最难的指针部分你已经基本掌握了

有哪一块还觉得模糊?可以直接告诉我,我再给你针对性拆解(比如多级指针、函数指针、const volatile组合、DMA指针操作等)。

http://www.jsqmd.com/news/294324/

相关文章:

  • 在Windows的VSCode上查看linux代码
  • 串口屏丨串口屏厂家丨串口屏方案丨恒域威串口屏 赋能精准分析:色谱仪专用显示屏的全链路适配方案解析
  • 写给自己
  • 2026英语雅思培训机构怎么选 全国优质辅导机构排行榜+核心解析家长必须考察的关键维度
  • 2026英语雅思培训机构辅导机构排行榜 家长择校全指南:多维度评测帮孩子选对适配备考机构
  • Linux 之 【日志】(实现一个打印日志的类)
  • 2026英语雅思考试培训辅导机构排行榜+核心解析 家长择校实用指南 精准匹配孩子雅思备考全阶段需求
  • Mermaid简记
  • 学长亲荐10个AI论文软件,助你搞定研究生毕业论文!
  • 计算机Java毕设实战-基于springboot的生产安全监测系统的设计与实现智慧生产安全系统【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • 2025假日欺诈:利用购物季的礼品卡骗局
  • Java计算机毕设之基于springboot的智慧生产安全系统基于SpringBoot的智慧工厂安全生产监督管理系统(完整前后端代码+说明文档+LW,调试定制等)
  • 2026英语雅思考试培训辅导机构排行榜 核心解析+适配人群指南 助力考生高效备考
  • 2026英语雅思考试培训辅导机构排行榜 备考择机构核心维度全解析:附高适配决策自查清单
  • 上海品牌设计4A公司2026年排行,设计服务谁更贴心?可靠的设计公司排行技术实力与市场典范解析
  • NMN哪个牌子效果最好?2026抗衰十大尖端NMN品牌排行榜盘点
  • 2026龙港净化工程公司,为生物制药改造添砖加瓦,洁净厂房/洁净车间/洁净室/无尘室,净化工程公司施工公司哪家靠谱
  • 常用的css
  • 学长亲荐2026TOP9AI论文软件:专科生毕业论文必备测评
  • 2026年了,还不知道匠厂AI?再晚一步,你的行业就被霸屏了。
  • ONNX模型转换避坑技巧
  • 网站安全太复杂?雷池SafeLine+cpolar实现“躺平式”防护! - 教程
  • 1000星巴克星礼卡回收多少,2026年划算的价格表一览
  • 2025年市面上优秀的横梁货架产品推荐,重型货架/货架/仓库货架/中型货架/层板货架,横梁货架供应商推荐排行榜单
  • 【ST表+二分】codeforces 359 D. Pair of Numbers
  • Mac系统安装nvm
  • 2026年武汉螺纹钢/线材/板材/管材源头厂家选购推荐:湖北鑫永盛钢铁贸易有限公司
  • 香橙派安装ch340驱动
  • 冲刺Day3
  • 实用指南:四旋翼无人机PID控制仿真模型探索