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

结构体变量和指针的构建和访问

导言:

大家在学习C语言的指针和结构体内容时,我们会尝试用一种更简单方便的方式去访问我们定义的结构体:定义结构体变量和结构体指针的方式.

那这两个变量有什么区别呢?第一行中的S为结构体_StuInfo的结构变量,第二行中的P为结构体_StuIfod的指针。那我们又该如何通过这些变量去访问到我们的结构体呢?变量访问的方式又有哪些误区呢?

正文:

1.核心概念:

在我们正式了解如何有效访问结构体之前,需要明确四个核心概念:

(1)结构体变量:实实在在,占有内存的结构体实例(就像上文图片中的S);

(2)结构体指针:储存结构体变量内存地址的变量(就像上文图中的P);

(3)内存偏移量: 结构体中每个成员相对于结构体起始地址的字节数 ;

例如在struct _StuInfo中,“score”可能在起始位置+0字节,而“Name”则在起始位置+4字节(一个int占4个字节)

(4) 变量的访问:根据变量的起始地址 + 数据类型的字节数,找到对应内存地址并读写数据。 ;

注意: 结构体作为 “复合类型”,其内存是连续的整块空间:结构体变量有一个起始地址,每个成员按定义顺序依次排列,每个成员的地址 = 结构体起始地址 + 该成员的偏移量

2.构建结构体变量和结构体指针

(1)构建结构体变量

构建结构体变量的本质是在栈上构建一块首地址与变量S相同的连续空间.当你定义一个这样的结构体变量时,编译器会执行以下的三个步骤:

1.计算出该结构体(_StuInfo)所需要的内存空间

2.在栈上构建出一块连续的空间,这块空间的首地址便是变量S的首地址

(若此时构建的结构体首地址为0x1000,则变量S的首地址也为0x1000)

3.结构体的每一个成员在这块连续的空间里面按照我们定义的顺序占用对应大小的内存

(2)构建结构体指针

构建结构体指针的本质是用一个普通变量来存储结构体的首地址.当你定义一个结构体指针,编译器除了会执行构建结构体的步骤,还会将结构体的首地址放到这个普通变量中.就好比你的盒子里装着不同样式和口味的巧克力,你将这个盒子放在了你的桌子上,然后用纸条记录下了这个盒子的位置,这里的"纸条"就是你构建的结构体指针.

注意事项:这里的变量p的地址与结构体的地址没有关联性,可以是任意的地址,但是p记录的内容是结构体的首地址

3.访问结构体变量和结构体指针

通过了解如何构建结构体变量和结构体指针,我们能够比较清楚的认识到访问结构体变量和指针的本质:访问变量相当于直接访问结构体的地址,访问指针相当于访问另一个普通变量中存储的结构体的地址.接下来让我们详细介绍一下具体的访问方法

(1)访问结构体变量的方法--(.)

从示例中我们可以看到访问结构体变量的方法是在变量名和需要访问的结构体对象中间加上一个"." 运算符,这个运算符直接根据结构体的绝对地址来计算出成员地址,并让CPU访问.

执行步骤(简化版):

1.读取结构体变量的绝对起始地址

2.根据结构体成员的内存偏移量,计算出所访问成员的地址

3.访问该地址

(2)访问结构体指针的方法--(->)

从这段代码中,我们可以看到访问结构体指针的方法是在变量名和需要访问的结构体对象中间加上一个"->" 运算符,这个运算符可以读取指针变量p中存储的结构体地址,然后根据结构体的绝对地址来计算出成员地址,让CPU访问.

执行步骤(简化版):

1.读取指针变量内存地址中记录的结构体的地址

3.根据结构体成员的内存偏移量和结构体的地址,计算出所访问成员的地址

3.访问该地址

(3)(->)和(.)的互通

从上面两个方法的介绍中,我们可以发现:(->)和(.)运算符的工作实质几乎是相同的,那这两个运算符是否能够互通呢?答案是肯定的,接下来我将会展示一段代码,并说明这两种运算符是如何互通的.

通过这段代码我们可以发现,我们在访问结构体指针的过程中使用了访问结构体变量的(.)运算符.这是因为原本的p变成了(*p),此时的(*p)是对p的解引用,可以等价于变量S.所以在此时是可以使用(.)运算符的,符合C语言运行规范.

4.真题应用

俗话说得好,实践是检验真理的唯一标准.让我们用一段代码来真实的感受一下结构体变量和指针的构造和访问.

(1)代码展示

在这段完整的代码中,我们运用到了顺序表的数据结构来存储数据.代码中的MyList为结构体SeqList类型的变量,因此使用(.)来访问对象;Base为结构体StuInfo类型的指针,因此应该使用(->)来访问对象.但是我们可以发现.Base和对象名的衔接处却并未使用这种运算符,而是仍然使用了(.)运算符,且完全合法,这是为什么呢?

(2)原因解析

以Base[i].Age为例.Base[i] 是 *(Base + i) 的语法糖,代表对 Base + i 这个地址解引用后得到的结构体变量,而非"指向"偏向 i 个内存地址的变量.因此可以使用(.)运算符.(*(Base+i)).Age与(Base+i)->Age等价.

注意事项:Base是指针,但Base[i]是变量

5.总结

本文较清晰的介绍了如何构建和访问结构体变量和指针,这也是作者在学习结构体的时候的一些困惑,希望能够帮助到大家,如果有错误和不准确的地方,欢迎大家交流指正!!下一篇文章我会写一些关于C语言输入函数scanf的内容,涵盖的数据类型会更多!!我们下篇文章再见!!!

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

相关文章:

  • VibeVoice在嵌入式设备上的轻量化部署教程
  • FireRedASR-AED-L边缘计算:树莓派部署实战
  • 终极网盘直链下载助手完整指南:免费快速突破限速
  • ARM开发者的福音:Trace32模拟器配置与调试全攻略(附常见问题解决方案)
  • 2025-2026年提升机厂家推荐:口碑好的品牌及详细选购避坑指南与用户真实反馈 - 十大品牌推荐
  • Spring注解
  • YOLOv10镜像教程:如何导出为TensorRT引擎实现极致加速
  • 阿里百亿级系统架构设计实录全网首次公开!
  • 2026年提升机厂家推荐:热门优选型号对比分析及行业应用场景深度解析 - 十大品牌推荐
  • FireRedASR Pro处理复杂音频效果展示:音乐与人声分离识别挑战
  • 基于51单片机的智能抢答器系统设计与实现
  • [源码导读] OpenClaw 架构深潜
  • 谷歌 Workspace 集成 Gemini:AI 办公功能全面升级
  • 2024蓝桥杯B组初赛--备战蓝桥杯版h
  • 小爱音箱设备发现异常深度排查与系统优化指南
  • K8s集群内服务访问失败?可能是FORWARD链在捣鬼(附永久修复方案)
  • PostGIS实现DEM分析之地形崎岖度指数计算【ST_TRI】
  • 雪女-斗罗大陆-造相Z-Turbo企业级应用:软件测试中的视觉用例自动生成
  • FPGA 进阶指南:Verilog 模块化设计实战与层次化架构优化
  • 512G MLC颗粒 固态U盘 DIY:从拆机片到高速存储的实战指南
  • 百度智能云千帆AppBuilder API调用全攻略:从密钥获取到实战示例
  • RMBG-2.0抠图实战案例:真人毛发、玻璃杯、宠物猫,复杂场景轻松应对
  • 70B模型上下文一变,ROI直接崩溃?揭秘AI算力瓶颈真相:数据流才是关键!“
  • Dify大模型API调用成本失控案例复盘(2024真实生产事故全链路追踪)
  • 使用CTC语音唤醒模型开发语音控制的智能健身系统
  • 避坑指南:YOLO-v8.3部署过程中常见问题与解决方案
  • TwinCAT3与台达伺服联调实战:版本不匹配导致的使能问题排查全记录
  • 互联网大厂Java求职者面试记:一场技术与幽默交织的面试
  • 突破平台限制:WorkshopDL让非Steam玩家高效获取创意工坊资源
  • 伏羲天气预报效果对比:FuXi vs GFS在东亚季风区温度预报MAE降低37%