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

C++ Primer Plus 重读精讲 _ 指针进阶全集:三类const指针辨析、指针数组数组指针硬核区分、指针地址传参、工控函数双向改参实战

全文连载前置回顾(前11篇完整知识链路)

正式开启第十二篇正文前,串联往期全部知识点,锚定本篇进阶指针的承接价值:

  1. 1-3篇:开发环境、程序基础骨架、工业标准化编码规范

  2. 4-6篇:基础变量、常量、全套运算符,掌握基础数据运算逻辑

  3. 7篇:分支结构,实现设备条件判断与阈值报警

  4. 9篇:三大循环+跳转关键字,完成数组循环遍历基础能力

  5. 8、10篇:一维/二维数组、字符数组、C风格字符串,搞定批量数据与文本报文存储

  6. 11篇:指针零基础入门,吃透内存地址、取地址&、解引用*、指针与数组联动、空指针&野指针避坑

上篇我们掌握了基础指针寻址、指针偏移遍历数组、串口报文指针解析,能够用指针直接操作内存数据。但在实际工控函数封装、多设备指针管理、只读报文地址保护场景中,基础指针完全不够用:想要保护报文数据不被误改、批量管理多组设备数组地址、在函数内部修改外部原始变量,都必须用到进阶指针语法。本篇一次性扫清进阶指针所有疑难概念,彻底解决指针学习分水岭难题。


前言

指针是C++学习的最大分水岭,绝大多数人卡在进阶指针阶段止步不前:分不清const修饰指针的三种写法、永远混淆指针数组和数组指针、不懂为什么函数形参无法修改实参原始数据、不清楚值传递和地址传递的底层差异。

教材往往只罗列语法,不讲底层内存区别和工程使用场景,导致开发者只会写代码,不懂为什么这么写,工控项目中经常出现:只读串口报文被意外篡改、函数内修改参数外部无变化、数组地址指针误用导致程序崩溃等隐性BUG。

本篇对应《C++ Primer Plus》指针进阶章节,延续系列重读深挖+工业落地风格,用通俗口诀+内存图解拆解三类const指针,一句话区分指针数组与数组指针,详解指针地址传参底层原理,搭配工控函数修改设备参数、多设备指针数组管理实战案例,汇总进阶指针全套踩坑点、搭配C#跨语言对照表,彻底打通指针全部知识体系。

一、三类const修饰指针(工控报文只读保护刚需)

工控开发中经常需要保护串口原始报文、设备固定参数地址,禁止误修改地址或地址内数据,const修饰指针分为三种写法,熟记口诀即可快速区分,不用死记硬背:

通用分辨口诀看*号位置,const修饰谁,谁就不能改

1. 常量指针:const修饰*(指向的数据不可改,指针地址可改)
constint*p=&a;
  • 限制规则:不能修改指针指向的值,可以修改指针指向的地址

  • 工控场景:只读串口原始报文,防止代码误改写缓冲区原始数据

  • 错误操作:*p = 100; // 编译报错,禁止修改数据

  • 合法操作:p = &b; // 可以更换指针指向的地址

2. 指针常量:const修饰指针变量(地址不可改,数据可改)
int*constp=&a;
  • 限制规则:不能修改指针存放的地址,可以修改指向的数据

  • 工控场景:指针固定绑定串口缓冲区首地址,禁止指针偏移乱跑

  • 错误操作:p = &b; // 编译报错,禁止修改地址

  • 合法操作:*p = 100; // 可以修改地址内部数据

3. 双const指针:地址和数据都不可改(最高权限只读)
constint*constp=&a;
  • 限制规则:指针地址、指向的数据全都无法修改

  • 工控场景:固定硬件寄存器地址,硬件地址和寄存器数据均禁止软件修改

  • 所有修改操作全部编译报错,极致内存安全保护

三类const指针快速汇总表
指针类型代码写法指针地址能否修改指向数据能否修改工业适用场景
常量指针const int* p✅ 可以修改❌ 不可修改只读报文缓冲区
指针常量int* const p❌ 不可修改✅ 可以修改固定硬件内存地址
双const指针const int* const p❌ 不可修改❌ 不可修改只读硬件寄存器

二、指针数组 VS 数组指针(全网最简区分,彻底告别混淆)

这是指针进阶最大难点,90%开发者长期混淆,本篇用优先级+一句话口诀永久区分,贴合工控多设备地址管理场景:

分辨核心规则:[]下标优先级 > *解引用优先级
口诀:谁先结合谁就是本体

1. 指针数组:存放指针的数组(数组为本体)
int*arr[5];
  • 结合逻辑:arr先和[]结合,本质是数组,数组中每一个元素都是int类型指针

  • 内存形态:连续内存空间,内部存储多个指针地址

  • 工控实战:批量存储多台设备数组首地址,统一管理多路传感器缓存

2. 数组指针:指向数组的指针(指针为本体)
int(*p)[5];
  • 结合逻辑:括号提升优先级,p先和结合,本质是指针,该指针专门指向一个长度为5的数组

  • 内存形态:仅占一个指针大小,指向一整块数组连续内存

  • 工控实战:直接指向二维数组行地址,快速遍历温度矩阵数据表

极简一句话总结
  • 指针数组:数组里面装指针(存多个地址)

  • 数组指针:指针指向整个数组(指向一整块数组内存)

三、指针做函数参数:地址传递核心原理(工业函数开发核心)

1. 值传递的致命缺陷

普通变量传参属于值传递,函数内部只是实参的副本,修改形参完全无法影响外部原始变量,工控开发中无法通过函数修改设备原始参数、原始报文数据。

2. 地址传递:指针传参底层逻辑

将变量内存地址传入函数,函数内部直接操作原始内存空间,无需副本,直接修改外部原始数据,这也是工控配置函数、参数校准函数的标准写法。

3. 代码对比:值传递 VS 地址传递
#include<iostream>// 1. 值传递:无法修改外部原始变量voidchangeValue(inta){a=999;}// 2. 地址传递:指针传参,直接修改外部原始变量voidchangeAddr(int*p){*p=999;}intmain(){intdeviceTemp=25;// 设备原始温度changeValue(deviceTemp);std::cout<<"值传递后温度:"<<deviceTemp<<std::endl;// 依旧25,无变化changeAddr(&deviceTemp);std::cout<<"地址传递后温度:"<<deviceTemp<<std::endl;// 变为999,原始数据被修改return0;}
4. 数组传参本质(串联前文知识点)

数组传入函数时,数组名自动退化为指针,不会拷贝整个数组内存,节省栈空间开销,这也是大数组传参必须用指针的核心原因。

四、独家C#语法机制对照(跨语言开发者必看)

进阶指针知识点C++C#工业开发差异说明
const修饰指针三类写法区分严格,地址/数据权限分离无原生指针const修饰,const仅修饰变量C#屏蔽内存权限管控,C++可精细化保护内存数据
指针数组/数组指针语法差异极大,误用直接编译报错无该两类指针概念,统一封装数组C#无需关心数组底层地址,C++必须严格区分
函数值传递/地址传递默认值传递,指针实现地址传递ref/out关键字实现地址传递效果C#用关键字替代指针传参,屏蔽底层内存细节
数组传参退化指针数组传参自动退化为指针,丢失长度信息数组传参保留完整Length属性C++数组传参必须手动传入长度常量

五、工控综合实战案例:指针传参修改设备阈值+指针数组管理多设备

整合本篇全部进阶指针知识点,还原上位机真实业务:通过指针函数动态修改设备高温报警阈值,用指针数组统一管理4台设备温度缓冲区地址,批量读取设备温度数据。

#include<iostream>// 指针传参:修改设备高温报警阈值voidsetWarnThreshold(double*warnPtr,doublenewVal){*warnPtr=newVal;}intmain(){// 全局设备报警阈值doublewarnTemp=80.0;// 1. 指针传参修改原始报警阈值setWarnThreshold(&warnTemp,85.0);std::cout<<"更新后设备高温报警阈值:"<<warnTemp<<"℃"<<std::endl;// 2. 定义4台设备温度数组doubledev1[]={25.1,26.3};doubledev2[]={82.5,27.9};doubledev3[]={78.2,30.1};doubledev4[]={22.6,24.8};// 指针数组:存放4个数组首地址,批量管理多设备double*devArr[]={dev1,dev2,dev3,dev4};constintDEV_NUM=4;std::cout<<"===== 指针数组批量读取设备温度 ====="<<std::endl;for(inti=0;i<DEV_NUM;i++){std::cout<<"第"<<i+1<<"台设备初始温度:"<<*(devArr[i])<<"℃"<<std::endl;}return0;}

六、重读专属:进阶指针八大高频工程踩坑总结

  • 坑1:const指针位置写错:混淆常量指针与指针常量,导致地址或数据意外被修改

  • 坑2:指针数组和数组指针漏写括号:少写括号直接改变变量本体,代码逻辑完全错乱

  • 坑3:值传递妄图修改外部变量:函数内修改无效,外部原始参数毫无变化

  • 坑4:数组传参后获取长度:数组退化为指针,sizeof无法获取真实数组长度

  • 坑5:双const指针非法赋值:同时修改地址和数据,直接编译报错

  • 坑6:数组指针遍历越界:数组指针指向行,偏移一步直接跳过一整行数据

  • 坑7:指针数组存放普通变量地址:类型不匹配,内存读取数据错乱

  • 坑8:函数指针参数未做空指针判断:传入空指针,函数内部解引用直接程序崩溃

七、原书课后习题重点解析

习题:封装指针函数,交换两个整数变量的值(必须修改原始实参)
#include<iostream>// 指针地址传参,交换两个原始变量值voidswapNum(int*a,int*b){inttemp=*a;*a=*b;*b=temp;}intmain(){intnum1=100;intnum2=200;std::cout<<"交换前:num1="<<num1<<" num2="<<num2<<std::endl;swapNum(&num1,&num2);std::cout<<"交换后:num1="<<num1<<" num2="<<num2<<std::endl;return0;}

核心考点:指针地址传参、函数内部修改外部原始变量、指针解引用取值赋值,是指针传参最经典工业面试+工程实操考题。

本篇总结

  • 三类const指针核心看*位置,按需保护指针地址或指向数据,适配工控只读内存场景

  • 指针数组存多个指针地址,数组指针指向一整块数组,依靠运算符优先级快速区分

  • 值传递仅拷贝副本无法改原值,指针地址传递直接操作原始内存,是函数改参唯一方案

  • 数组传参自动退化指针,工程中必须手动传入数组长度常量,规避长度丢失问题

下篇预告

下一篇第十三篇:C++ string标准字符串类精讲,彻底告别易乱码、需要手动维护\0结束符的C风格字符数组,详解string构造、拼接、查找、截取、常用成员函数,搭配串口字符串报文格式化实战,补齐C++全部字符串处理能力!

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

相关文章:

  • VMware虚拟机组网通信全链路解析(ESXi 7.0+vSphere 8.0实测验证)
  • 面向对象——多态
  • Focus架构:视觉语言模型的高效加速方案
  • 群辉Nas部署GitServer随笔
  • 别再被Python列表拷贝坑了!浅拷贝深拷贝,一个不注意就让你代码崩盘
  • 如何快速查找 *Bash* 命令的*类型*?
  • File和IO
  • 与你的 Elasticsearch 数据对话:使用 Google ADK 和 MCP 构建一个实时语音 agent ,分为 3 个组件
  • 5分钟快速上手:RedisDesktopManager-Windows终极可视化数据库管理工具完整指南
  • 告别串口乱码!STM32F401RCT6用Arduino框架点灯+串口打印保姆级教程
  • C#工业视觉实战:集成工业相机与YOLOv8实现缺陷检测系统
  • 探索兴趣爱好的内涵
  • 廖雪峰Python2教程PDF!20行代码秒杀C语言1000行,速度慢?谁在乎
  • 别再让激光器‘发烧’了!手把手教你用运放搭建高精度恒流源(附LTspice仿真文件)
  • 如何生成字母或数字的*序列*?
  • Dify平台大模型接入实战:从云端API到本地部署全流程指南
  • Postman便携版终极指南:Windows用户的免安装API开发解决方案
  • 别再只会用三极管了!用JFET搭个恒流源给LED调光,实测效果稳如老狗
  • 电脑弹窗拦截工具绿色免费超好用
  • 48.可直接落地!IEC61131-3 ST 完整源码|PLC 物料分拣 + PID 调速 + Modbus 通信
  • 零基础入门MySQL数据分析:从SQL语法到电商实战项目
  • SH9递归对抗驱动的活系统:九层架构理论体系深度研究报告(世毫九实验室原创研究)
  • linux中TCP通信
  • Python之rickshaw包语法、参数和实际应用案例
  • 基于PANDAS的QAbstractTableModel实现高级TableView详细解析(八、在TableView实现冻结窗口)
  • Confluence高危漏洞CVE-2022-26134应急响应与安全加固实战指南
  • 把 Enterprise Services Repository 配成一座稳定的集成设计中枢
  • 洛谷 P2024:[NOI2001] 食物链 ← 扩展域并查集
  • SpringBoot 底层原理完整教程(上篇・配置文件与配置优先级)
  • Anthropic揭秘Claude隔离内幕、加州政府半价用上AI、主权AI来了:今天6件大事