内存对齐计算方法(偏移量)

news2024/10/2 14:36:58

内存对齐简单来讲就是把一个数据存放到内存中,其内存的地址要与数据自己大小为整数倍。 处理器在执行指令去操作内存中的数据,这些数据通过地址来获取。 当一个数据所在的地址和它的大小对齐的时候,就说这个数据对齐了,否则就是没对齐。

内存对齐是以空间换时间的方法,计算机一次就可以把存储的数据提取出来,极大提高了效率。

 首先以结构体为例来阐明是如何计算的。

 结构体对齐规则:

1.1

第一个成员的地址在结构体变量偏移量为0的地址处。

1.2 

其中对齐数=编译器默认的一个对齐数与该成员大小的较小值。(vs默认为8)

1.3 

其他成员变量依次要按照对齐数的整数倍的地址处来存放。

1.4 

结构体总体的大小要为最大对齐数的整倍数。(每一个成员变量都有自己的对齐数,与1.3描述的对象不一样)

1.5

如果一个结构体里面包含一个结构体,把其看作一个成员就行(但其整体对齐数不能看作一个对齐数来比是否为最大对齐数)。

 简单看个例子:

#include <stdio.h>
struct s1
{
	char a;
	int b;
	char c;
};
struct s2
{
	char a;
	char b;
	int c;
};
struct s3
{
	int c;
	char a;
	char b;
};
int main()
{
	struct s1 q = { 0 };
	struct s2 w = { 0 };
	struct s3 e = { 0 };
	printf("%d\n", sizeof(q));
	printf("%d\n", sizeof(w));
	printf("%d\n", sizeof(e));
	return 0;
}

结果:

12
8
8

D:\VS\Project4\x64\Debug\Project4.exe (进程 13452)已退出,代码为 0。
按任意键关闭此窗口. . .

分析:

三个结构体其中包含的成员一样,但为什么打印的结果不一样呢?这就用到了内存对齐了。

先看s1在内存中真实的存储:

               a
                b
                b
                b
                b
                c

12刚好是最大对齐数4的整数倍,所以此处即为完整内存大小。

                  结束

注释:
1. char类型所占字节为1,比默认对齐数8要小,所以对齐数是1。

2. int类型所占字节为4,比默认对齐数8要小,所以对齐数是4。

3.所以最大对齐数就是4。

4. 而其他成员变量依次要按照对齐数的整数倍的地址处来存放。所以要往下偏移(浪费)3个节大小,再往下就是4,来存放int类型,存完int类型时为8,

5. 再来一个char类型,对齐数为1,所以现在内存大小为9,

6. 此外还要满足是最大对齐数的整数倍,所以还要再偏移(浪费)3个字节大小,即为12。

于是s2在内存中真实的存储:

                    a
                    b
                     
                     c
                     c
                     c

                     c

                   结束

注释:

1. 一个char类型,对齐数为1,所以存放在了0地址处,

2. 再来一个char类型,对齐数为1,所以现在内存大小为2,

3. 接下来是int类型,所以要往下偏移2个字节大小,再存放int的4个字节,

4. 现在内存大小为8,刚好是最大内存数4的整数倍。即为8。

5. 同理可得s3在内存中真实的存储情况,有兴趣的小伙伴可自行研究一下哈。

当结构体里面包含一个结构体呢?

如:

#include <stdio.h>
struct s1
{
	char a;
    int  b;
	char c;
};
struct s2
{
	struct s1 s;
	char a;
	char b;
	int c;
};

int main()
{
	printf("%d\n", sizeof(s2));
	return 0;
}

结果:

20

D:\VS\Project4\x64\Debug\Project4.exe (进程 9968)已退出,代码为 0。
按任意键关闭此窗口. . .

分析:

1. 先来排结构体s,一个char类型,一个int类型,在一个char类型。最大对齐数是4,所以最后结果是12。

2. 再来一个char类型,对齐数为1,直接在后面存就行,所以现在内存大小为13。

3. 再来一个char类型,内存大小变为14。

4. 因为最大对齐数为 4, 14 不是4的倍数,所以会往后偏移(浪费)2个字节大小,变为16,再来存放int的4个字节,即为20。

此外补充两个知识点:

一:

#pragma pack (4)

表示设置默认对齐数为4。

#pragma pack ()

表示取消设置的默认对齐数。

二:

offsetof 可计算偏移量大小。

size_t offsetof(struct name, nember name);

(成员相当于类型的偏移量)。

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

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

相关文章

【GO】29.go-gin支持ssl/tls,即https示例

本文为演示采用自签名证书一.生成证书通过openssl工具生成证书1.1 安装opensslmacos通过brew安装brew install openssl1.2 生成跟证书私钥openssl genrsa -out ca.key 40961.3 准备配置文件vim ca.conf内容如下[ req ] default_bits 4096 distinguished_name req_disti…

光耦合器的定义与概述

光耦合器或光电耦合器是一种电子元件&#xff0c;基本上充当具有不同电压电平的两个独立电路之间的接口。光耦合器是可在输入和输出源之间提供电气隔离的常用元件。它是一个 6 引脚器件&#xff0c;可以有任意数量的光电探测器。 在这里&#xff0c;光源发出的光束作为输入和输…

设计模式第7式:适配器模式与外观模式

前言 前面讲的装饰者模式是将对象包装起来&#xff0c;并赋予新的职责。适配器模式同样是包装对象&#xff0c;但是目的不一样&#xff0c;它要让某些对象的接口看起来不像自己而是像别的东西。为什么要这样做&#xff0c;因为可以将类的接口转换成想要的接口。还会讲一个适配…

C++中的枚举与位域

枚举在传统 C中&#xff0c;枚举类型并非类型安全&#xff0c;枚举类型会被视作整数&#xff0c;则会让两种完全不同的枚举类型可以进行直接的比较&#xff08;虽然编译器给出了检查&#xff0c;但并非所有&#xff09;&#xff0c;甚至同一个命名空间中的不同枚举类型的枚举值…

GPR后期功能整理

基金本子写得太困难了&#xff0c;学术水平不够&#xff0c;好的想法未想到好的科学问题&#xff0c;难以下笔。和龙工沟通后&#xff0c;得到了大量impulse radar的数据&#xff0c;后期需要进行分析&#xff0c;从而能让GPR智能识别走得更远。从数据解译角度&#xff0c;找到…

配置CMAKE编译环境:VSCODE + MinGW

一. MinGW安装 MinGW(Minimalist GNU For Windows)是个精简的Windows平台C/C、ADA及Fortran编译器&#xff0c;相比Cygwin而言&#xff0c;体积要小很多&#xff0c;使用较为方便。 MinGW最大的特点就是编译出来的可执行文件能够独立在Windows上运行。 MinGW的组成&#xff…

[Linux]进程替换

&#x1f941;作者&#xff1a; 华丞臧. &#x1f4d5;​​​​专栏&#xff1a;【LINUX】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站 文…

HashMap设计思想学习

HashMap设计思想学习引言树化与退化红黑树的优势索引计算put流程扩容&#xff08;加载&#xff09;因子为何默认是 0.75fhashMap并发丢失数据问题jdk 1.7并发死链问题key 的设计引言 hashmap在jdk 1.7之前是数组链表结构&#xff0c;而jdk1.8之后变为是数组(链表|红黑树) 树化…

【第38天】不同路径数问题 | 网格 dp 入门

本文已收录于专栏&#x1f338;《Java入门一百例》&#x1f338;学习指引序、专栏前言一、网格模型二、【例题1】1、题目描述2、解题思路3、模板代码4、代码解析5.原题链接三、【例题2】1、题目描述2、解题思路3、模板代码4、代码解析5.原题链接三、推荐专栏四、课后习题序、专…

大型物流运输管理系统源码 TMS源码

大型物流运输管理系统源码 TMS是一套适用于物流公司的物流运输管理系统&#xff0c;涵盖物流公司内部从订单->提货->运单->配车->点到->预约->签收->回单->代收货款的全链条管理系统。 菜单功能 一、运营管理 1、订单管理&#xff1a;用于客户意向订…

ChatGPT 到底强大在哪里?(文末有彩蛋)

ChatGPT 是由 OpenAI 开发的一个人工智能聊天机器人程序&#xff0c;于2022年11月推出。该程序使用基于 GPT-3.5 架构的大型语言模型并通过强化学习进行训练。ChatGPT 以文字方式交互&#xff0c;而除了可以通过人类自然对话方式进行交互&#xff0c;还可以用于相对复杂的语言工…

一定要收藏的面试思维导图,粉丝分享面试经验

一位粉丝分享面试经验&#xff1a;1.常见面试题有哪些&#xff1f;主要从以下一些知识点做了准备&#xff1a; 常用的分析方法、Excel、SQL、 A/B测试、产品分析。然后每份面试针对职位要求&#xff0c;还有前期和HR聊天一点点了解这个职位之后&#xff0c;定向准备。 Excel、S…

OpenMMLab 实战营打卡 - 第 7 课

OpenMMLab MMSegmentation内容概要MMSegmentation统一超参MMSegmentation 的项目结构分割模型的模块化设计分割模型的配置文件主干网络的配置ResNet v1c主解码头的配置辅助解码头的配置数据集配置数据处理流水线常用训练策略参考资料内容概要 • MMSegmentation 项目概述 • M…

TSDF算法应用与源码详解

数据与代码链接见文末 1.TSDF整体概述 (1)需要准备的输入 1.原始图片;2.对应的深度信息;3.每张图的相机位姿;4.相机内参 原始输入图像数据(就是一个场景多个视角拍摄的结果) 输入图像的深度信息,位姿信息等(一般由相机得到,也可以通过算法得到) (2)整体概述…

【DFS并查集】岛屿数量

经典的dfs/bfs问题&#xff0c;给一个起点开始搜索&#xff0c;满足条件则继续调用dfs/bfs 从没有访问过的某个陆地出发&#xff0c;将所有能到达的陆地的状态都记录为已访问。下次出发不从已访问的陆地出发&#xff0c;每次出发前都把岛屿数 1即可 class Solution { public…

STM32开发(9)----CubeMX配置外部中断

CubeMX配置外部中断前言一、什么是中断1.STM32中断架构体系2.外部中断/事件控制器&#xff08;EXTI&#xff09;3.嵌套向量中断控制器&#xff08;NIVC&#xff09;二、实验过程1.CubeMX配置2.代码实现3.硬件连接4.实验结果总结前言 本章介绍使用STM32CubeMX对引脚的外部中断进…

MySQL 3:MySQL数据库基本操作 DQL

数据库管理系统的一个重要功能是数据查询。数据查询不应简单地返回数据库中存储的数据&#xff0c;还应根据需要对数据进行过滤&#xff0c;确定数据的显示格式。MySQL 提供了强大而灵活的语句来实现这些操作。MySQL数据库使用select语句查询数据。 select [all|distinct]<…

09- 机器学习经典流程 (中国人寿保费项目) (机器学习)

删除特征: data data.drop([region, sex], axis1)特征数据调整: data.apply( ) # 体重指数&#xff0c;离散化转换&#xff0c;体重两种情况&#xff1a;标准、肥胖 def convert(df,bmi):df[bmi] fat if df[bmi] > bmi else standardreturn df data data.apply(convert, …

EXCEL-职业版本(1)

EXCEL职业版本(1) 工作表 插入 注&#xff1a;默认会在鼠标选中的sheet后面新增&#xff0c;例如图中&#xff0c;当前选中的是sheet2&#xff0c;点击新增后会在sheet2后面自动新增一个sheet 删除 移动或者复制 类似于copy一整个sheet的所有内容 step1 右击【sheet名称】选…

Cordova

一、简介 Cordova 是用 Web 技术&#xff08; HTML&#xff0c;CSS 和 JS &#xff09;构建移动应用的平台。我们可以认为Cordova 是一个容器&#xff0c;用于将的 Web 应用移植到移动端&#xff0c;同时支持移动端的功能&#xff08;例如&#xff1a;定位、蓝牙、摄像头等&am…