【C++】讲的最通透最易懂的关于结构体内存对齐的问题

news2024/11/16 7:42:24

目录

  • 1. 内存对齐规则
  • 2. 简单易懂的内存对齐示例
    • 2.1 简单结构体
    • 2.2 含位域的结构体
    • 2.3 空类的大小
    • 2.4 嵌套结构体
  • 3. 为什么需要内存对齐?
  • 4. 类型在不同系统下所占字节数

1. 内存对齐规则

  1. 第一个成员在与结构体变量偏移量为0的位置处。
  2. 其他成员变量要对齐到某个数字(对其数)的整数倍的地址处。对其数=编译器默认的一个对齐数与该成员大小的较小者。vs中默认的值是8 Linux中默认的值是4
  3. 结构体总大小为最大对其数(每一个成员变量都有一个对其数)的整数倍。
  4. 如果嵌套了结构体对齐到自己的最大对其数是整数倍处,结构体的整体大小就是最大对齐数(含嵌套结构体的对齐数)的整数倍。
  5. 如对内存对齐有明确要求,可用#pragma pack(n)指定(n必须是2的N次方),以n和结构体中最长数据成员长度中较小者为有效值

可能只看上面的描述你还是有点搞不懂,那么我们可以看一下具体的例子和视图讲解:

struct s1{
	char c1;
	int i;
	char c2;
};
//结构体总大小为:12

在这里插入图片描述

2. 简单易懂的内存对齐示例

2.1 简单结构体

struct s1
{
	char str;  //1字节
	short x;   //2字节
	int num;   //4字节
};
// sizeof(s1) = 8     // (1+1) + 2 + 4 = 8  第2个加1处的内存是空的

2.2 含位域的结构体

一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。

struct s2
{
	unsigned char a:7;  //字段a占用了一个字节的7个bit

	unsigned char b:2;  //字段b占用了2个bit

	unsigned char c:7;  //字段c占用了7个bit
}s1;
// sizeof(s1) = 3  // 1 + 1 + 1 = 3
struct s3
{
	char t : 4;   //4表示在一个字节中占4个比特位
	char k : 4;
}; 
// sizeof(s3) = 1   //0.5 + 0.5 = 1
struct s4
{
	char t : 4;   //4表示在一个字节中占4个比特位
	char k : 4;
	unsigned short i : 8;
	char a;
}; 
// sizeof(s4) = 6   //(0.5 + 0.5 + 1) + 2 + (1+1) = 6
// 解释:0.5和0.5占一个字节,两个占4比特的刚好可以放在一个字节中,short为2字节,对齐数是2,所以0.5 + 0.5 + 1中加的1是空的

2.3 空类的大小

class A {};
// sizeof(A) = 1

空类,没有任何成员变量和成员函数,编译器是支持空类实例化对象的,对象必须要被分配内存空间才有意义,大小: 1Byte (字节)

2.4 嵌套结构体

class A {
private:
    double dd;
    int ii;
    int* pp;
};

class Test {
private:
    int i;
    A a;
    double d;
    char* p;
};
int main()
{
	A a1;
	Test test;
	cout << sizeof(a1) << endl;
	cout << sizeof(test) << endl;
}
// x86(32位操作系统)平台运行结果:40
// x64(64位操作系统)平台运行结果:48

对其数 = 编译器默认的一个对齐数与该成员大小的较小者,vs中默认的值是8

  • x86:指针是4字节,类A的大小是16,8与16的较小者是8。内存大小为:8 + 16 + 8 + 4 = 36,又因为36不是最大对齐数8的倍数,所以内存向后偏移,大小为 40

  • x64:指针是8字节,类A大小为24,8与24的较小者是8。内存大小为:8 + 24 + 8 +8 = 48,48刚好是最大对齐数8的倍数,所以内存大小为48

3. 为什么需要内存对齐?

字节对齐主要是为了提高内存的访问效率

cpu一次能读取多少内存要看数据总线是多少位,如果是16位,则一次只能读取2个字节,如果是32位,则可以读取4个字节,并且cpu不能跨内存区间访问
假设有这样一个结构体如下:

struct s
{
    char a;
    int b;
};

假设地址空间是类似下面这样的:
在这里插入图片描述

  • 在没有字节对齐的情况下,变量a就是占用了0x00000001这一个字节,而变量b则是占用了0x00000002~0x000000005这四个字节,那么cpu如果想从内存中读取变量b,首先要从变量b的开始地址0x00000002读到0x0000004,然后再读取一次0x00000005这个字节,相当于读一个int,cpu从内存读取了两次。

  • 而如果进行字节对齐的话,变量a还是占用了0x00000001这一个字节,而变量b则是占用了0x00000005~0x00000008这四个字节,那么cpu要读取变量b的话,就直接一次性从0x00000005读到0x00000008,就一次全部读取出来了。

  • 所以说,字节对齐的根本原因其实在于cpu读取内存的效率问题,对齐以后,cpu读取内存的效率会更快。结构体的内存对齐是拿空间来换取时间的做法

4. 类型在不同系统下所占字节数

类型win32win64linux32linux64
char1111
short2222
int4444
long4448
long long8888
float4444
double8888
void*(指针)4848

在这里插入图片描述

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

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

相关文章

学了很久python却什么都做不了?这个方法一定要试试

很多人学了两三个月的python却什么都做不了&#xff0c;但有的人只学了不到一个月的时间&#xff0c;就可以开始自己做项目或者接私活&#xff0c;这是为什么&#xff1f; 作为20年码龄的老程序员&#xff0c;龙叔我觉得除了内在原因外&#xff0c;学习资源占据着大头。拥有好的…

NOC2021年测试卷2

一、单选题(共25题,每题2分,共50分) 1. 执行下面程序,屏幕上最多会看到多少个苹果?( ) A、10个B、11个C、1个D、无法确定2. 关于下面程序,说法正确的是 ?( ) 3. “角色1”要在“角色2”说完话后才能开始动作,如果“角色2”思考2秒钟,然后说3秒钟,那么“角…

【干货】又是一年跳槽季!Nginx 10道核心面试题及解析

Nginx是一款轻量级的高性能Web服务器和反向代理服务器&#xff0c;由俄罗斯的Igor Sysoev开发。它具有占用资源少、高并发、稳定性高等优点&#xff0c;被广泛应用于互联网领域。在Nginx的面试过程中&#xff0c;面试官通常会提出一些核心问题&#xff0c;本文将介绍一些常见的…

【手把手教会数据类型的存储】

数据类型介绍整型在内存中的存储&#xff1a;原码、反码、补码大小端字节序介绍及判断浮点型在内存中的存储解析1.数据类型介绍我们已经学习过了基本的数据类型&#xff1a;整型&#xff1a;shor —— 短整型int —— 整型long —— 长整型long long —— 更长的整型浮点型&…

机器学习 | 线性回归(单变量)

前文回顾&#xff1a;机器学习概述&#x1f4da;线性回归概念我们要使用一个数据集&#xff0c;数据集包含俄勒冈州波特兰市的住房价格。在这里&#xff0c;我要根据不同房屋尺寸所售出的价格&#xff0c;画出我的数据集。比方说&#xff0c;如果你朋友的房子是 1250 平方尺大小…

数据仓库之建模理论以及仓库设计思想

1、数据仓库 1.1、数据仓库概述 数据仓库是一个为数据分析而设计的企业级数据管理系统。数据仓库可集中、整合多个信息源的大量数据&#xff0c;借助数据仓库的分析能力&#xff0c;企业可从数据中获得宝贵的信息进而改进决策。同时&#xff0c;随着时间的推移&#xff0c;数…

【计算机组成原理】1、浮点数的二进制表示、科学计数法、IEEE754标准

文章目录什么是浮点数浮点数表示数字浮点数的二进制表示浮点数的「IEEE754标准」二进制表示背景特殊约定示例浮点数为什么有精度损失浮点数的范围和精度有多大参考资料用定点数表示数字时&#xff0c;会约定小数点的位置固定不变&#xff0c;整数部分和小数部分分别转换为二进制…

中原银行使用 XSKY星辰天合对象一体机解决核心系统备份管理问题

中原银行使用星辰天合 X3000 对象存储一体机在生产中心和灾备中心分别搭建分布式存储集群&#xff0c;通过 S3 协议与 NBU 备份平台对接&#xff0c;提供海量存储服务&#xff0c;实现备份平台架构转型。 近年来&#xff0c;金融机构随着业务规模及数据量的持续增长&#xff0c…

JavaSE19-常见类

文章目录一、Object1.概述2.常用方法二、String1.概述2.对象创建2.1 直接使用字面值2.2 使用构造方法3.常用方法三、包装类1.概述2.创建对象2.1 直接使用字面值2.2 使用构造方法2.3 使用静态方法valueOf3.常用方法4.自动装箱与自动拆箱4.1 自动装箱4.2 自动拆箱4.3 原理四、Str…

各类特殊开关电源问题解决方案

一、提高DCDC芯片电流 使用大功率三极管代替芯片内部开关管提高过流能力 二、BUCK电路实现负电压 将buck的地作为-Vout输出&#xff0c;原输出接地。 注&#xff1a;不要用LM2596跟LM2576 三、FLY-BUCK电路 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20808c03b126…

成功解决xshell7会话窗口只能显示一个的问题

文章目录前言一. 问题复现二. 问题解决方法一方法二三. 拓展3.1 自定义快捷键3.2 将当前shell中的代码内容复制到记事本中3.3 xshell配置密钥登录3.3.1 生成密钥3.3.2 将密钥上传到服务器并设置3.3.3 用xshell密钥登录服务器总结前言 重点强调&#xff1a; 本文是解决xshell的…

Linux系列 使用vi文本编辑器

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.vi文本编辑器 1.使用vi文本编辑器 2.vi编辑器的工作模式 3.命令模式中的…

【LeetCode】剑指 Offer(13)

目录 题目&#xff1a;剑指 Offer 31. 栈的压入、弹出序列 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 写在最后&#xff1a; 题目&#xff1a;剑指 Offer 31. 栈…

重写toString()方法-课后程序(JAVA基础案例教程-黑马程序员编著-第十二章-课后作业)

【案例12-1】&#xff1a;重写toString()方法 【案例介绍】 1.案例描述 为了方便输出对象&#xff0c;Object类提供了toString()方法。但是该方法的默认值是由类名和哈希码组成的&#xff0c;实用性并不强。通常需要重写该方法以提供更多的对象信息。 本案例要求使用反射重…

3D可视化大屏制作真的那么难?没有好用的软件解决吗?

有多少人印象里的数据可视化大屏还是像这样的二维大屏&#xff1f;这种二维可视化大屏早就不能满足审美日益提高的大众了。 现在用的都是3D可视化大屏&#xff0c;这种结合了3D技术的可视化形式不仅让数据更加的清晰&#xff0c;也增加了美感&#xff0c;这观看体验&#xff…

【数据结构】单链表——增删查改【万字介绍】

目录 一&#xff0c;线性表 1&#xff0c;什么是线性表 2&#xff0c;线性表的结构 二&#xff0c;链表 1&#xff0c;什么是链表 2&#xff0c;链表的分类 3&#xff0c;单链表的特点 三&#xff0c;链表的实现 1&#xff0c;结构的定义 2&#xff0c;创建一个新结点 3&#…

ChatGPT 不是黑魔法,“替代搜索引擎”言之尚早

ChatGPT 火了。整个 LLM 和搜索领域都已经在过去几个月内发生了翻天覆地的变化。ChatGPT 不再是一个玩具&#xff0c;它开始被微软、谷歌集成在搜索以及各个 SaaS 服务中&#xff0c;且取得了令人惊叹的效果。我尝试着使用 ChatGPT 回答过去一个月搜索过的 30 个问题&#xff0…

10个必须知道的JavaScript技巧,让你成为更好的程序员

1.Promise回调地狱Promises 提供了一种优雅的方式来处理 JavaScript 中的异步操作。这也是避免“回调地狱”的解决方案之一。但是我并没有真正理解它的意思&#xff0c;所以我写了这段代码。我做了这些事情&#xff1a;先获取用户的基本信息。按用户信息获取所有文章的简要摘要…

SPI_Master驱动程序框架

SPI_Master驱动程序框架 文章目录SPI_Master驱动程序框架一、SPI传输概述1.1 数据组织方式1.2 SPI控制器数据结构二、 SPI传输函数的两种方法2.1 老方法2.2 新方法致谢参考内核源码: drivers\spi\spi.c 一、SPI传输概述 1.1 数据组织方式 使用SPI传输时&#xff0c;最小的传…

hutool日期工具类相关:获取某月所有周、某周的起止时间或所有日期、计算连续天数

目录前言实现1、获取当月的所有周2、根据指定的第几周&#xff0c;获取这周的开始、结束时间3、获取当前月某一周的所有日期4、多个日期中&#xff0c;计算最大的连续天数5、判断指定日期是否在某个范围内前言 最近做项目&#xff0c;碰到一个比较复杂的日期查询方式&#xff…