结构体(位段)内存分配

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

  首先,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位。
访问和修改由于位段的行为可能因编译器而异,因此在使用位段时应格外小心。在访问或修改位段的值时,可能需要使用位操作(如按位与、按位或、位移等)来确保数据的正确性。
可移植性由于位段的行为可能因编译器和平台而异,因此在使用位段时应考虑代码的可移植性。如果可能的话,最好避免在需要跨平台兼容性的代码中使用位段。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/642879.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux驱动开发笔记(二) 基于字符设备驱动的I/O操作

文章目录 前言一、设备驱动的作用与本质1. 驱动的作用2. 有无操作系统的区别 二、内存管理单元MMU三、相关函数1. ioremap( )2. iounmap( )3. class_create( )4. class_destroy( ) 四、GPIO的基本知识1. GPIO的寄存器进行读写操作流程2. 引脚复用2. 定义GPIO寄存器物理地址 五、…

视频汇聚平台LntonCVS视频监控系统前端错误日志记录及Debug模式详细讲解

LntonCVS作为一种支持GB28181标准的流媒体服务平台,旨在提供一个能够整合不同厂商设备、便于管理和扩展的解决方案,以适应日益复杂的视频监控环境。通过实现设备的统一管理和流媒体的高效传输,LntonCVS帮助构建更加灵活和强大的视频监控系统。…

Andoird使用Room实现持久化及使用Room进行增删查改

文章目录 Room概述Room的使用一、在gradle.build中添加依赖库kotlinJava 创建实体类创建抽象Dao层接口创建DataBase层使用创建的查看数据库 总结: 这篇文章会告诉你如何在Android中通过kotlin或者Java来实现数据持久化 Room概述 处理大量结构化数据的应用可极大地受…

强烈推荐 20.7k Star!企业级商城开源项目强烈推荐!基于DDD领域驱动设计模型,助您快速掌握技术奥秘,实现业务快速增长

更多资源请关注纽扣编程微信公众号 1 项目简介 商城是个从零到一的C端商城项目,包含商城核心业务和基础架构两大模块,推出用户、消息、商品、订单、优惠券、支付、网关、购物车等业务模块,通过商城系统中复杂场景,给出对应解决方案。使用 …

Java——简易图书管理系统

本文使用 Java 实现一个简易图书管理系统 一、思路 简易图书管理系统说白了其实就是 用户 与 图书 这两个对象之间的交互 书的属性有 书名 作者 类型 价格 借阅状态 而用户可以分为 普通用户 管理员 使用数组将书统一管理起来 用户对这个数组进行操作 普通用户可以进…

Axure RP 10汉化版修改文字

效果 安装目录 lang/default Axure 10 RP 汉化包(概览改图层)

Express 的 req 和 res 对象

新建 learn-express文件夹,执行命令行 npm init -y npm install express 新建 index.js const express require(express); const app express();app.get(/, (req, res, next) > {res.json(return get) })app.post(/, (req, res, next) > {res.json(retur…

单机一天轻松300+ 最新微信小程序拼多多+京东全自动掘金项目、

现代互联网经济的发展带来了新型的盈利方式,这种方法通过微信小程序的拼多多和京东进行商品自动巡视,以此给商家带来增加的流量,同时为使用者带来利润。实践这一手段无需复杂操作,用户仅需启动相应程序,商品信息便会被…

【东山派Vision K510开发板试用笔记】WiFi配网问题

目录 概述 WiFi配网的修改 悬而未决的问题 概述 最近试用了百问网提供的东山派Vision开发板,DongshanPI-Vision开发板是百问网针对AI应用开发设计出来的一个RSIC-V架构的AI开发板,主要用于学习使用嘉楠的K510芯片进行Linux项目开发和嵌入式AI应用开发…

闲话 .NET(5):.NET Core 有什么优势?

前言 .NET Core 并不是 .NET FrameWork 的升级版,它是一个为满足新一代的软件设计要求而从头重新开发的开发框架和平台,所以它没有 .NET FrameWork 的历史包袱,相对于 .NET FrameWork,它具备很多优势。 .NET Core 有哪些优势&am…

什么是DDoS流量清洗?

随着互联网的飞速发展,网络安全问题日益凸显,其中分布式拒绝服务(DDoS)攻击尤为引人关注。为了有效应对这一威胁,流量清洗服务应运而生,成为网络安全领域的一项重要技术。 流量清洗服务是一种专门针对DDoS…

最小生成树【做题记录】c++(Prim,Kruskal)

目录 Prim算法求最小生成树 【算法思想】 【算法实现】 【数据结构设计】 【算法步骤】 【输入输出】 【代码示例】 Kruskal算法求最小生成树 【算法思想】 判断是否会产生回路的方法 【算法描述】 【图的存储结构】 【输入输出】 【代码示例】 Prim算法求最小生…

Reactor设计模式

Reactor设计模式 Reactor模式称为反应器模式或应答者模式,是基于事件驱动的设计模式,拥有一个或多个并发输入源,有一个服务处理器和多个请求处理器,服务处理器会同步的将输入的请求事件以多路复用的方式分发给相应的请求处理器。…

Android 自定义图片进度条

用系统的Progressbar,设置图片drawable作为进度条会出现图片长度不好控制,容易被截断,或者变形的问题。而我有个需求,使用图片背景,和图片进度,而且在进度条头部有个闪光点效果。 如下图: 找了…

Nginx部署静态网页

1、首先拿到前端给的dist包,上传到服务器指定位置:/ajd/dist 2、找到nginx.conf配置文件,修改 server {listen 9300;server_name xxx.xx.xx.xx;location / {root /ajd/dist;try_files $uri $uri/ /index.html;index index.html …

电赛一等奖!基于TMS320F2812的简易数字频率计

电赛一等奖!简易数字频率计设计(原理图、PCB、源码、分析报告) 这份文件是关于合肥工业大学电气与自动化工程学院的一个项目报告,题目为“基于TMS320F2812的简易数字频率计”。项目由方敏、侯其立、李苗、张巧云四位本科生完成&am…

区块链技术和应用

文章目录 前言 一、区块链是什么? 二、区块链核心数据结构 2.1 交易 2.2 区块 三、交易 3.1 交易的生命周期 3.2 节点类型 3.3 分布式系统 3.4 节点数据库 3.5 智能合约 3.6 多个记账节点-去中心化 3.7 双花问题 3.8 共识算法 3.8.1 POW工作量证明 总结 前言 学习长…

XILINX FPGA DDR 学习笔记(一)

DDR 内存的本质是数据的存储器,首先回到数据的存储上,数据在最底层的表现是地址。为了给每个数据进行存放并且在需要的时候读取这个数据,需要对数据在哪这个抽象的概念进行表述,我们科技树发展过程中把数据在哪用地址表示。一个数…

2. C++服务器编程-信号

什么是信号 其实信号就是一个中断。就是在执行程序的时候突然来了一个信号,然后我们去执行这个新来的程序了,这就是中断。 处理方法 信号的处理方式∶忽略、捕获、默认处理 linux中都有那些信号 man7 signal 比如说kill -9 安装man中文手册 自己百…

单片机LCD1602显示电子时钟设计

基于52单片机电子时钟的设计 摘要 本次设计的多功能时钟系统采用STC89C52单片机为核心器件,利用其定时器/计数器定时和记数的原理,结合液晶显示电路、时钟芯片DS1302电路、电源电路以及按键电路来设计计时器。将软硬件有机地结合起来,使得系…