结构体字节对齐、偏移量

news2024/11/18 11:18:15

复习下struct的大小、成员偏移量offsetof,说下我的理解:

64位下默认对齐数default=8
原则1:struct中每一个成员变量tmp的对齐数real=min{default,tmp}

struct Student {
    int num;//0
    char name[8];
    double score;
} stu;

这个结构体stu中,第一个成员num为int的对齐数real_num=min{8,4}=4。
第二个成员name为char类型,对齐数real_name=min{8,1}=1。
第三个成员score为double类型,对齐数real_score=min{8,8}=8。
原则2:偏移量offsetof必须是real的倍数
1,所以第一个成员num偏移量startid=0*real_num=0*4=0,从startid开始size1=4即4个bytes被用掉即[id=0~3已用]。

2,因为上面size1=4已用4个bytes。第二个成员name偏移量是startid=real_name*倍数=1*倍数>3,故此时倍数取4,所以偏移量startid=4,而name的size2=8,所以id=4~11已用。


3,因为上面size1+size2=12已用12个bytes。而第三个成员score的偏移量startid=real_score*倍数=8*倍数,必需>11,所以倍数不能取0或1,只能取2,所以startid=8*2=16,即从16开始放score,而score的大小size3=8,此时id=16~23已用。所以stu这个结构体在内存中就是如下的样子:

所以stu的size等于id=0一直到id=23即size=24。所以逻辑是先计算偏移量,再自然计算得到struct整体的大小。

struct Test1 {
    int x;
    double y;
} t1;
struct Test2 {
    int x;
    char y[8];
} t2;

在t1中,对x来说 real_x=min{8,4}=4 偏移量startid=real_x*倍数=4*0=0,size1=4,id=0~3被使用。
在t1中,对y来说 real_y=min{8,8}=8偏移量startid=real_y*倍数=8*倍数,同时必需>3,所以倍数就是1,startid=8。

当你换成char y[8]后,如结构体t2所示:对y来说,real_y=min{8,1}=1 偏移量startid=real_y*倍数=1*倍数,同时必需>3,所以倍数就是4,startid=4。

由此可见,t1和t2偏移量不一样,所以struct的size是不一样的。虽然它们的成员变量都是4bytes、8bytes,但终究偏移量不同导致了结构体大小的不同。

原则3:struct的对齐数等于其所有成员real对齐数的最大值。

所以对于结构体嵌套结构体的情况,我们易知:

struct Student {
    int num;
    char name[8];
    double score;
};

struct CombineStudent {
    short memb;
    Student originstruct[2];
    char lastmem[3];
} comstu;

现在结构体Student(由之前分析知结构体的size为24字节)作为新结构体comstu的成员,且个数为2的数组originstruct。
根据原则3,结构体Student的对齐数real_stu=max(real_num,real_name,real_score)=max(4,1,8)=8

对于结构体comstu:
1,第一个成员memb为short的对齐数real_mem=min{8,2}=2。偏移量startid=0*real_mem=0*2=0 而short占2字节即[id=0~1已用]。

2,第二个成员originstruct为Student类型,对齐数real_originstruct=min{8,8}=8,偏移量startid=倍数*real_originstruct=倍数*8,必须>1,故倍数=1,即偏移量startid=1*8=8。而每个Student占24字节现在有2个Student即[id=8~8+24*2-1也就是8~55已用]。
3,第三个成员lastmem为char类型,对齐数real_lastmem=min{8,1}=1,偏移量startid=倍数*real_lastmem=倍数*1,必须>55,故倍数取56即可,startid=56,而每个char占1字节现在共3个,共id=56~58已用。
但你以为结构体comstu的大小就是id=0~58=59吗?!天真,还有原则4!

原则4:结构体的总大小size必须是对齐数real的整数倍

所以虽然上面的结构体comstu的id=0~58=59,但结构体CombineStudent的real_comstu=max(real_memb,real_originstruct,real_lastmem)=max(2,8,1)=8!但是我们之前算好的59并不是real_comstu的整数倍!所以后面必须要补几位直到占到id=63,即id=0~63总size=64才是CombineStudent的大小!

所以大家这下明白为啥C++建议我们定义变量时按从一定的顺序去定,如换个位置:

struct Combine2Student {
    short memb;
    char lastmem[3];
    Student originstruct[2];
} ;

刚刚的结构体CombineStudent如果换成这样,结果就不一样了,可以节约内存。大家可以算算:

real_memb=min{8,2}=2,size1=2,startid=0是real_memb的倍数,占id=0~1;

real_lastmem=min{8,1}=1,size2=3,startid=2是real_lastmem的倍数,占id=2~4;

real_originstruct=min{8,8}=8,size3=24*2=48,startid=8是real_originstruct的倍数,占id=8~55;

算到这里,总id=0~55=56已经是real_Combine2Student=max(real_memb,real_lastmem,real_originstruct)=max(2,8,1)=8的倍数了,所以不需再补!所以结构体Combine2Student的size=56!

调换位置后命名相同的三个成员,但结构体Combine2Student就是比ComebineStudent占内存少!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

阿里前端二面经典手写面试题汇总

实现类的继承 实现类的继承-简版 类的继承在几年前是重点内容,有n种继承方式各有优劣,es6普及后越来越不重要,那么多种写法有点『回字有四样写法』的意思,如果还想深入理解的去看红宝书即可,我们目前只实现一种最理想…

rollup环境配置

VUE2.x源码学习笔记 1. rollup环境配置 首先在VScode中新建文件夹vue_sc,然后终端打开定位到打开的文件夹,输入“npm init -y”初始化配置项,运行成功之后文件夹新增package.json文件 继续在终端运行"npm install babel/preset-env ba…

浅析Tomcat架构上的Valve内存马(内存马系列篇十一)

写在前面 这篇也是在Tomcat容器上面构造的内存马(收回之前说的不搞Tomcat了),这是建立在Tomcat的管道上面做文章的一个内存马的实现方式。这是内存马系列的第十一篇文章了。 前置 什么是Pipeline-Valve管道? 根据前面Tomcat架构的相关知识&#xff0…

腾讯云卖向“有币”区块链

曾经坚决“不涉币”的腾讯云将业务延伸向“有币区块链”。 在首届 Web3 全球峰会“腾讯云Web3构建日”上,腾讯云宣布进军Web3,并公开了与Ankr、Avalanche、Scroll和Sui 四个原生区块链项目的合作,其中前两个项目都发行了加密货币&#xff0c…

关于Java中的静态块讲解

文章目录类的加载特性与时机类加载的特性类加载的时机static的三个常用地方什么是静态块?特点写法静态块 static怎么用?类的加载特性与时机 在介绍static之前可以先看看类的相关 类加载的特性 在JVM的生命周期里,每个类只会被加载一次。 类加载的原则&#xf…

老板让我在Linux中使用traceroute排查服务器网络问题,幸好我收藏了这篇文章!

一、前言 作为网络工程师或者运维工程师,traceroute命令不会陌生,它的作用类似于ping命令,用于诊断网络的连通性,不过traceroute命令输出的命令会比ping命令丰富的多,可以跟踪从源系统到目标系统的路径。 很多工程师…

jsp城乡信息管理系统

技术:Java、JSP等摘要:管理信息系统(Management System,简称MS)是一个由管理人员和计算机组成的用以进行信息的收集、传输、加工、存储、维护和使用的系统。它是一门综合了管理科学,系统理论,计…

WSL2:开发环境安装

写在前面 主要是记录一下如何安装和搭建基于WSL2的开发环境;参考博文:搭建优雅的Windows终端 Windows terminalscoopstarship; 一、安装WSL2 以管理员身份运行CMD,执行以下命令即可WSL和Linux的默认Ubuntu发行版: …

【聚类】谱聚类解读、代码示例

【聚类】谱聚类详解、代码示例 文章目录【聚类】谱聚类详解、代码示例1. 介绍2. 方法解读2.1 先验知识2.1.1 无向权重图2.1.2 拉普拉斯矩阵2.2 构建图(第一步)2.2.1 ϵ\epsilonϵ 邻近法2.2.2 k 近邻法2.2.3 全连接法2.3 切图(第二步&#xf…

基于jeecgboot的flowable的H5版本在演示系统发布

目前在NBCIO 亿事达企业管理平台上发布了H5的在线演示系统,欢迎大家批评指正。 在nbcio-vue nbcio-vue: NBCIO 亿事达企业管理平台前端代码,基于ant-design-vue-jeecg的前端版本: 3.0.0代码和和flowable6.7.2,初步完成了集流程设…

【Linux】安装MySQL

目录 1.检测当前系统是否安装过MySQL相关数据库 2. 卸载现有的MySQL数据库 3.上传解压 4.顺序安装rpm包 5.启动MySQL 6.查看临时密码 7.登录MySQL 8.开放端口 1.检测当前系统是否安装过MySQL相关数据库 需要通过rpm相关指令,来查询当前系统中是否存在已安…

无法将“django-admin”项识别为cmdlet,函数,脚本文件或可运行程序的名称问题

无法将“django admin”项识别为cmdlet,函数,脚本文件或可运行程序的名称问题 小提示:首先检查一下有没有拼写错误!!!没有的话请继续 我们要知道django装到哪里去了 pip show django 注意:3.0…

Flutter(二)第一个Flutter应用

1.默认应用 在Android Studio中创建好项目以后,项目的入口即是lib下的main.dart import package:flutter/material.dart;void main() {runApp(const MyApp()); } //无状态的组件(Stateless widget) class MyApp extends StatelessWidget {}…

基于paddlex的C#环境配置及其部署【附带安装包】

前言 最近应老师要求部署一个基于paddlex的C#环境,踩了一些坑,经过几个版本的安装测试,最终成功,这里记录一下。此次用到的所有软件的安装包如下: 补充的vs 2019安装包: 官方参考链接(没有环…

Meta利用视觉信息来优化3D音频模型,未来将用于AR/VR

我们知道,Meta为了给AR眼镜打造智能助手,专门开发了第一人称视觉模型和数据集。与此同时,该公司也在探索一种将视觉和语音融合的AI感知方案。相比于单纯的语音助手,同时结合视觉和声音数据来感知环境,可进一步增强智能…

ERD Online 4.0.9 在线数据库建模、元数据管理平台(免费、私有部署)

ERD Online 是全球第一个开源、免费在线数据建模、元数据管理平台。提供简单易用的元数据设计、关系图设计、SQL查询等功能,辅以版本、导入、导出、数据源、SQL解析、审计、团队协作等功能、方便我们快速、安全的管理数据库中的元数据。 4.0.9 ❝ feat(erd): 主键生…

Opencv项目实战:21 美国ASL手势识别

0、项目介绍 首先,我可以保证在这里,你并不需要多么了解深的机器学习算法,我的初衷是通过本项目,激发大家学习机器学习的动力。选择这种手势原因是因为只有24个字母,你的电脑足以带的动,虽然我只训练A、B、…

group by聚合分组后如何获取分组数据

之前用group by分组后一直困惑怎么把分组后的数据拿到,因为分组后同一组的只有一条数据,最后发现了group_concat函数。记录一下,以后能用。语法:group_concat( [distinct] 要连接的字段 [order by 排序字段 asc/desc ] [separator…

【MySQL - InnoDB 存储结构】行格式详解

我们平时对 MySQL 的了解都只是限制在使用层面上,但是难道你就没有一个时刻好奇 MySQL 的内部结构嘛,我们通过 SQL 语句插入的一条条记录在 MySQL 底层到底是以什么格式存储的呢 ? 本文就将以 InnoDB 存储引擎为例子,介绍 MySQL 存…

专科top4|临床医生CSC公派博士后美国凯斯西储大学医院赴职

Q医生符合CSC公派博士后申报条件,我们先为其取得Hopkins的邀请函并获CSC批准,后因导师失联,为保险起见,我们又继续申请并获得凯斯西储大学医学院彩虹宝宝和儿童医院的邀请函,该院连续20年被评为全美最好儿童医院&#…