结构体(位段)内存分配
结构体由多个数据类型的成员组成。那编译器分配的内存是不是所有成员的字节数总和呢?
首先,stu的内存大小并不为29个字节,即证明结构体内存不是所有成员的字节数和。
其次,stu成员中sex的内存位置不在21,即可推测name成员起始内存位置在0。
接着,stu成员中sex与age内存并不连续,两者相隔4个字节。
最后,sty成员中的sex与score内存连续,但sty的内存大小与sex的内存位置也是数值差4。
那结构体的内存分配满足何种规则呢?
序号 | 结构体内存对齐规则 |
---|---|
1 | 结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处 |
2 | 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处 |
3 | 对⻬数=编译器默认的⼀个对⻬数与该成员变量⼤⼩的较⼩值 |
4 | VS 中默认的值为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位。 |
访问和修改 | 由于位段的行为可能因编译器而异,因此在使用位段时应格外小心。在访问或修改位段的值时,可能需要使用位操作(如按位与、按位或、位移等)来确保数据的正确性。 |
可移植性 | 由于位段的行为可能因编译器和平台而异,因此在使用位段时应考虑代码的可移植性。如果可能的话,最好避免在需要跨平台兼容性的代码中使用位段。 |
相关文章:

结构体(位段)内存分配
结构体由多个数据类型的成员组成。那编译器分配的内存是不是所有成员的字节数总和呢? 首先,stu的内存大小并不为29个字节,即证明结构体内存不是所有成员的字节数和。 其次,stu成员中sex的内存位置不在21,即可推测…...

基于SSH的母婴用品销售管理系统带万字文档
文章目录 母婴商城系统一、项目演示二、项目介绍三、系统部分功能截图四、万字论文参考五、部分代码展示六、底部获取项目源码和万字论文参考(9.9¥带走) 母婴商城系统 一、项目演示 母婴商城系统 二、项目介绍 基于SSH的母婴商城系统 系统…...

说些什么好呢
大一:提前学C和C。学完语法去洛谷或者Acwing二选一,刷300道左右题目。主要培养编程思维,让自己的逻辑能够通过代码实现出来。 现在对算法有点感兴趣但是没有天赋,打不了acm,为就业做准备咯。 大二(算法竞赛)࿱…...

1301-习题1-1高等数学
1. 求下列函数的自然定义域 自然定义域就是使函数有意义的定义域。 常见自然定义域: 开根号 x \sqrt x x : x ≥ 0 x \ge 0 x≥0自变量为分式的分母 1 x \frac{1}{x} x1: x ≠ 0 x \ne 0 x0三角函数 tan x cot x \tan x \cot x …...

C语言之指针进阶(3),函数指针
目录 前言: 一、函数指针变量的概念 二、函数指针变量的创建 三、函数指针变量的使用 四、两段特殊代码的理解 五、typedef 六、函数指针数组 总结: 前言: 本文主要讲述C语言指针中的函数指针,包括函数指针变量的概念、创建…...

RabbitMQ安装及配套Laravel使用
MQ MQ 全称 Message Queue(消息队列),是在消息的传输过程中保存消息的容器。多用于系统之间的异步通信。 为什么需要mq: 解耦:MQ能够使各个系统或组件之间解耦,降低它们之间的耦合度,提高系统的灵活性和可维护性异步处理:通过MQ可以实现异步处理,提高系统响应速度和吞…...

java在类的定义中创建自己的对象?
当在main方法中新建自身所在类的对象,并调用main方法时,会不断循环调用main方法,直到栈溢出 package com.keywordStudy;public class mainTest {static int value 33;public static void main(String[] args) throws Exception{String[] sn…...

掌握C++回调:按值捕获、按引用捕获与弱引用
文章目录 一、按引用捕获和按值捕获1.1 原理1.2 案例 二、弱引用2.1 原理2.2 案例一2.3 案例二:使用base库的弱引用 三、总结 在C回调中,当使用Lambda表达式捕获外部变量时,有两种捕获方式:按值捕获和按引用捕获。 一、按引用捕获…...

抖音运营_如何做出优质的短视频
目录 一 短视频内容的构成 1 图像 2 字幕 3 声音 4 特效 5 描述 6 评论 二 短视频的热门类型 1 颜值圈粉类 2 知识教学类 3 幽默搞笑类 4 商品展示类 5 才艺技能类 6 评论解说类 三 热门短视频的特征 1 产生共鸣 2 正能量 3 紧跟热点话题 4 富有创意 四 短视…...

Day21:Leetcode513.找树左下角的值 +112. 路径总和 113.路径总和ii + 106.从中序与后序遍历序列构造二叉树
LeetCode:513.找树左下角的值 解决方案: 1.思路 在遍历一个节点时,需要先把它的非空右子节点放入队列,然后再把它的非空左子节点放入队列,这样才能保证从右到左遍历每一层的节点。广度优先搜索所遍历的最后一个节点…...

Java数据结构和算法(B树)
前言 B树又叫平衡的多路搜索树;平衡的意思是又满足平衡二叉树的一些性质,左树大于右树; 多路意思是,可以多个结点,不再是像二叉树只有两个结点; 实现原理 B树是一种自平衡的搜索树,通常用于实…...

成为程序员后我都明白了什么?从入行到弃坑?
作为一个入行近10年的php程序员,真心感觉一切都才刚开始,对计算机,编程语言的理解也好,程序员中年危机也罢,之前都是听别人说的,真的自己到了这个水平,这个年龄才深刻体会到这其中的种种。 我一…...

python --创建固定字符串长度,先进先出
a 123def concatenate_within_limit(b, new_string):# 计算新字符串与a的长度之和a btotal_length len(a) len(new_string)# 如果长度超过1024,从前面删除足够的字符if total_length > 5:diff total_length - 5a a[diff:] new_string # 删除前diff个字符…...

容器化部署
目录 docker容器化部署 怎样使用Docker Compose或Kubernetes等容器编排工具来管理和扩展联邦学习系统 使用Docker Compose...

国产数据库TiDB的常用方法
TiDB的常用方法主要涉及安装配置、数据操作、性能调优以及监控和维护等方面。以下是对这些常用方法的归纳和介绍: 1. 安装与配置 安装TiDB:根据官方文档的指引,用户可以按照步骤进行TiDB的安装。配置TiDB:安装完成后,…...

基于DdddOcr通用验证码离线本地识别SDK搭建个人云打码接口Api
前言 最近介绍了一款免费的验证码识别网站,识别效率太低,考虑到ddddocr是开源的,决定搭建搭建一个,发现原作者sml2h3已经推出好久了,但是网上没有宝塔安装的教程,于是本次通过宝塔搭建属于自己的带带弟弟OCR通用验证码离线本地识别 原项目地址:https://github.com/sml2…...

2、xss-labs之level2
1、打开页面 2、传入xss代码 payload:<script>alert(xss)</script>,发现返回<script>alert(xss)</script> 3、分析原因 打开f12,没什么发现 看后端源码,在这form表单通过get获取keyword的值赋给$str&am…...

人才测评的应用:人才选拔,岗位晋升,面试招聘测评
人才测评自诞生以来,就被广泛应用在各大方面,不仅是我们熟悉的招聘上,还有其他考核和晋升,都会需要用到人才测评。不知道怎么招聘?或者不懂得如何实现人才晋升?都可以参考人才测评,利用它帮我们…...

前端面试题日常练-day33 【面试题】
题目 希望这些选择题能够帮助您进行前端面试的准备,答案在文末。 在jQuery中,以下哪个选项用于在元素上绑定一个点击事件? a) click() b) bind() c) on() d) trigger() jQuery中,以下哪个选项用于获取元素的属性值? …...

非整数倍数据位宽转换24to128
描述 实现数据位宽转换电路,实现24bit数据输入转换为128bit数据输出。其中,先到的数据应置于输出的高bit位。 电路的接口如下图所示。valid_in用来指示数据输入data_in的有效性,valid_out用来指示数据输出data_out的有效性;clk是时…...

html通过数据改变,图片跟着改变
改变前 改变后 通过数据来控制样式展示 <template><div>通过num控制图标是否更改{{num}}<div class"box"><!-- 如果num大于1则是另一种,样式,如果小时1,则是另一种样式 --><div class"item&qu…...

centos7.9 安装SqlServer
1、导入Microsoft SQL Server CentOS存储库: sudo curl -o /etc/yum.repos.d/mssql-server.repo https://packages.microsoft.com/config/rhel/7/mssql-server-2019.repo2、安装SQL Server: sudo yum install -y mssql-server假如机器内存不足2G 需要对…...

Idea中flume的Interceptor的编写教程
1.新建-项目-新建项目 注意位置是将来打包文件存放的位置,即我们打包好的文件在这/export/data个目录下寻找 2. 在maven项目中导入依赖 Pom.xml文件中写入 <dependencies> <dependency> <groupId>org.apache.flume</groupId> <artifa…...

java单元测试:JUnit测试运行器
JUnit测试运行器(Test Runner)决定了JUnit如何执行测试。JUnit有多个测试运行器,每个运行器都有特定的功能和用途。 1. 默认运行器 当没有显式指定运行器时,JUnit会使用默认运行器,这在JUnit 4和JUnit 5之间有所不同…...

网络模型—BIO、NIO、IO多路复用、信号驱动IO、异步IO
一、用户空间和内核空间 以Linux系统为例,ubuntu和CentOS是Linux的两种比较常见的发行版,任何Linux发行版,其系统内核都是Linux。我们在发行版上操作应用,如Redis、Mysql等其实是无法直接执行访问计算机硬件(如cpu,内存…...

智能语义识别电影机器人的rasa实现
文章目录 0.前言1.项目整体框架2.rasa训练数据结构4.rasa启动命令及用到的API 0.前言 最近做了一个智能电影机器人的项目,我主要负责用户语义意图识别,用的框架是rasa,对应的版本为 3.6.15,对应的安装命令为: pip3 install rasa…...

C# 实现腾讯云 IM 常用 REST API 之会话管理
目录 关于腾讯 IM REST API 开发前准备 范例运行环境 常用会话管理API 查询账号会话总未读数 查询单聊会话消息记录 下载最近会话记录 小结 关于腾讯 IM REST API REST API 是腾讯即时通信 IM 提供给服务端的一组 HTTP 后台管理接口,如消息管理、群组管理…...

MySQL之Schema与数据类型优化(三)
Schema与数据类型优化 BLOB和TEXT类型 BLOB和TEXT都是为存储很大的数据而设计的字符串数据类型,分别采用二进制和字符方式存储。 实际上它们分别属于两组不同的数据类型家族:字符类型是TINYTEXT,SMALLTEXT,TEXT,MEDIUMTEXT,LONG…...

大语言模型发展历史
大语言模型的发展历史可以追溯到自然语言处理(NLP)和机器学习早期的探索,但真正快速发展起来是在深度学习技术兴起之后。以下是大语言模型发展的一个简要历史概述: 早期阶段(20世纪50-90年代): …...

Nginx - 安全基线配置与操作指南
文章目录 概述中间件安全基线配置手册1. 概述1.1 目的1.2 适用范围 2. Nginx基线配置2.1 版本说明2.2 安装目录2.3 用户创建2.4 二进制文件权限2.5 关闭服务器标记2.6 设置 timeout2.7 设置 NGINX 缓冲区2.8 日志配置2.9 日志切割2.10 限制访问 IP2.11 限制仅允许域名访问2.12 …...