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

结构体(位段)内存分配

   结构体由多个数据类型的成员组成。那编译器分配的内存是不是所有成员的字节数总和呢?
在这里插入图片描述

  首先,stu的内存大小并不为29个字节,即证明结构体内存不是所有成员的字节数和。
  其次,stu成员中sex的内存位置不在21,即可推测name成员起始内存位置在0。
  接着,stu成员中sex与age内存并不连续,两者相隔4个字节。
  最后,sty成员中的sex与score内存连续,但sty的内存大小与sex的内存位置也是数值差4。

那结构体的内存分配满足何种规则呢?

序号结构体内存对齐规则
1结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处
2其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处
3对⻬数=编译器默认的⼀个对⻬数与该成员变量⼤⼩的较⼩值
4VS 中默认的值为8,Linux中gcc没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩
5结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的整数倍。
6如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。

利用以上规则,我们就可以合理解释文章开头的疑问了。
在这里插入图片描述
  char类型对齐数为1,可以储存在任意位置;
  int类型对齐数为4,必须储存在内存位置为4的倍数;
  sty结构体内存大小必须是成员最大对齐数的整数倍;

  从以上分析,我们可以得出结构体存在内存浪费。而避免浪费内存的最好编程习惯就是将成员字节数小的整合在一起。

  结构体(struct)在C和C++编程语言中是一种复合数据类型,它允许你将不同类型的数据项(变量)组合成一个单一的变量名。位段(Bit-fields)是结构体中的一种特殊成员,它允许程序员指定每个成员所占用的位数,而不是使用整个字节或更大的内存空间。位段通常用于硬件编程或需要精确控制内存使用的场合。

位段的基本语法如下:

struct {  type member_name : width;  // 其他成员...  
} structure_name;type 是基础数据类型(通常是整数类型),它决定了位段的基本存储单位。
member_name 是位段的名称。
width 是一个整数,指定了该位段所占用的位数。
structure_name 是结构体的名称。

示例
下面是一个使用位段的简单示例:
在这里插入图片描述

应用场景
硬件寄存器访问·  在硬件编程中,许多设备的寄存器由一系列位组成,每个位表示设备的不同状态、配置选项或标志。使用位段可以方便地访问和控制这些位,而无需进行复杂的位运算或掩码操作。    ·  例如,一个硬件设备的状态寄存器可能有多个位字段,分别表示设备的不同状态。通过使用位段,程序员可以直接通过结构体的成员名来访问这些位字段,从而简化代码并提高可读性。
节省存储空间·  当需要存储大量的小规模数据时,位段可以有效地节省存储空间。例如,在过程控制、参数检测或数据通信等应用中,控制信息往往只占一个字节中的一个或几个二进制位。通过使用位段,可以将多个这样的信息存储在一个字节中,从而节省存储空间。                   ·   参考文章提到,位段能够把长度为奇数的数据包装在一起,节省存储空间。当程序需要成千上万个这样的结构体时,选择位段是比较明智的。
访问整数值的部分内容·  位段允许程序员方便地访问一个整数值的部分内容。这在处理包含多个不同含义的位的整数值时非常有用。通过定义位段,可以将整数值分解为多个有意义的字段,并直接访问这些字段的值。
·  例如,在TCP/IP协议中,数据包头通常由多个字段组成,每个字段占用不同的位数。通过使用位段,可以方便地解析数据包头并提取所需的字段值。
提高代码可读性·  通过使用位段,可以将整数值分解为多个有意义的字段,并为每个字段分配一个具有描述性的名称。这有助于提高代码的可读性和可维护性。程序员可以更容易地理解代码的目的和功能,并更轻松地修改和维护代码。
注意事项
跨平台和编译器差异位段的具体行为可能因编译器和平台而异。不同的编译器可能会对位段的布局、填充和访问方式进行不同的解释。因此,在使用位段时,应确保你的代码在所有目标平台上都能正常工作。
内存对齐编译器可能会在位段之间插入填充字节,以确保结构体成员在内存中的对齐。这可能会导致位段的实际内存布局与你在代码中指定的不同。
位段的大小限制位段的大小通常受到其基础数据类型大小的限制。例如,如果你使用unsigned int作为位段的基础数据类型,并且你的系统中unsigned int是32位的,那么任何unsigned int位段的最大宽度都不能超过32位。
访问和修改由于位段的行为可能因编译器而异,因此在使用位段时应格外小心。在访问或修改位段的值时,可能需要使用位操作(如按位与、按位或、位移等)来确保数据的正确性。
可移植性由于位段的行为可能因编译器和平台而异,因此在使用位段时应考虑代码的可移植性。如果可能的话,最好避免在需要跨平台兼容性的代码中使用位段。
http://www.lryc.cn/news/353108.html

相关文章:

  • 基于SSH的母婴用品销售管理系统带万字文档
  • 说些什么好呢
  • 1301-习题1-1高等数学
  • C语言之指针进阶(3),函数指针
  • RabbitMQ安装及配套Laravel使用
  • java在类的定义中创建自己的对象?
  • 掌握C++回调:按值捕获、按引用捕获与弱引用
  • 抖音运营_如何做出优质的短视频
  • Day21:Leetcode513.找树左下角的值 +112. 路径总和 113.路径总和ii + 106.从中序与后序遍历序列构造二叉树
  • Java数据结构和算法(B树)
  • 成为程序员后我都明白了什么?从入行到弃坑?
  • python --创建固定字符串长度,先进先出
  • 容器化部署
  • 国产数据库TiDB的常用方法
  • 基于DdddOcr通用验证码离线本地识别SDK搭建个人云打码接口Api
  • 2、xss-labs之level2
  • 人才测评的应用:人才选拔,岗位晋升,面试招聘测评
  • 前端面试题日常练-day33 【面试题】
  • 非整数倍数据位宽转换24to128
  • html通过数据改变,图片跟着改变
  • centos7.9 安装SqlServer
  • Idea中flume的Interceptor的编写教程
  • java单元测试:JUnit测试运行器
  • 网络模型—BIO、NIO、IO多路复用、信号驱动IO、异步IO
  • 智能语义识别电影机器人的rasa实现
  • C# 实现腾讯云 IM 常用 REST API 之会话管理
  • MySQL之Schema与数据类型优化(三)
  • 大语言模型发展历史
  • Nginx - 安全基线配置与操作指南
  • 简述js的事件循环以及宏任务和微任务