【C++】内存对齐

本篇文章介绍C++中的内存对齐,后续介绍C的union和C++的variant的时候,需要用到这部分的知识。

占用内存

先回忆下C++各个数据类型占用的内存大小:

  1. int:所占内存大小:4byte = 32bit;
  2. char:所占内存大小:1byte = 8bit;

还有其他的数据类型,但是今天就只用这两个。
我们写个结构体:

struct s{
    int x;
    char y;
};

它占用多少byte的内存呢?并不是4+1=5,而是4+4=8.

int main()
{
    printf("%d\n",sizeof(s));  // 输出8
    return 0;
}

结果

分析内存

处理器并不是按字节块来存取内存的。它一般会以2字节,4字节,8字节,16字节甚至32字节为单位来存取内存.我们将上述这些存取单位称为内存存取粒度.写代码的人一般会觉得所有数据结构都会像数组一样有随机存取的特性,变量之间是紧挨着的,但是对于不同类型的变量来说,从内存向寄存器转移数据的过程并不总是顺利的。

以下图片来自https://blog.csdn.net/dxpqxb/article/details/90485917,我懒得画图了,就直接用现成的了。

现在有4byte的数据存放在内存中,他们的地址如下:

数据首地址末地址
A03
B14

假设内存存取粒度是1byte,取A和B都只需要取4次即可
1byte
当内存存取粒度是2byte时,A只需要取两次,分别为0和1、2和3;但是B从1开始,取2次取到了1、2和3,第4byte的数据还没取到,因此还需要取一次,总共取了3次。同时,还要把无用的第0byte和第5byte数据丢掉。
2byte
当内存存取粒度是4byte时,同样的道理,A只需要取1次4byte,B则需要取2次,并丢弃第0,第5-7byte的数据。
4byte
现在有了内存对齐的,int类型数据只能存放在按照对齐规则的内存中,比如说0地址开始的内存。那么现在该处理器在取数据时一次性就能将数据读出来了,而且不需要做额外的操作,提高了效率。
内存对齐

内存对齐

内存对齐的一个原则就是,不要让变量跨内存存取粒度存储。

每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。gcc中默认#pragma pack(4),可以通过预编译命令#pragma pack(n),n = 1,2,4,8,16来改变这一系数。

有效对齐值:是给定值#pragma pack(n)和结构体中最长数据类型长度中较小的那个。有效对齐值也叫对齐单位。

了解了上面的概念后,我们现在可以来看看内存对齐需要遵循的规则:

  1. 结构体第一个成员的偏移量(offset)为0,以后每个成员相对于结构体首地址的 offset 都是该成员大小与有效对齐值中较小那个的整数倍,如有需要编译器会在成员之间加上填充字节。

  2. 结构体的总大小为 有效对齐值 的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。

我们看下面三个结构体:

#include <stdio.h>
struct x1
{
    int i;
    char c1;
    char c2;
};

struct x2
{
    char c1;
    int i;
    char c2;
};

struct x3
{
    char c1;
    char c2;
    int i;
};

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

有效对齐值为4

不考虑结构体本身对外的偏移量,我们以x1为例,i的大小是4,有效对齐值也是4,只要保证偏移量为4的整数倍就行,因此i占用0,1,2,3;c1和c2的大小都是1,有效对齐值为4,只要保证偏移量为1的整数倍即可,因此占用4和5;结构体本身需要对外对齐,必须是4的整数倍,因此将6和7填充上。其他两个结构体也是一样的分析方式。

现在我们改变有效对齐值为2,输出结果如下:
有效对齐值为2
依然以x1为例,i的大小为4,有效对齐值是2,只要保证偏移量为2的整数倍就行,因此i占用0,1,2,3;c1和c2的大小都是1,有效对齐值为2,只要保证偏移量为1的整数倍即可,因此占用4和5;结构体本身需要对外对齐,必须是2的整数倍,无需填充。

其他

C++11

对齐的英文是alighment,C++11引入了一个函数alignof,可以直接获取类型T的内存对齐要求,也就是最大的成员大小与有效对齐值中较小那个。比如当有效对齐值为4时,上面3个结构体的alignof结果都是4.

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

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

相关文章

视频智能分析支持摄像头异常位移检测,监测摄像机异常位移变化,保障监控状态

我们经常在生产场景中会遇到摄像头经过风吹日晒&#xff0c;或者异常的触碰&#xff0c;导致了角度或者位置的变化&#xff0c;这种情况下&#xff0c;如果不及时做出调整&#xff0c;会导致原本的监控条件被破坏&#xff0c;发生事件需要追溯的时候&#xff0c;查不到对应位置…

Kubernetes复习总结(一):Kubernetes内置资源、Device Plugin机制

1、Kubernetes内置资源 1&#xff09;、Pod Pod是Kubernetes进行管理的最小单元&#xff0c;程序要运行必须部署在容器中&#xff0c;而容器必须存在于Pod中 Pod可以认为是容器的封装&#xff0c;一个Pod中可以存在一个或者多个容器 1&#xff09;Pod进程组 在Kubernetes里面…

cookie和session、请求转发和重定向

会话 分为有状态会话和无状态会话 在HTML中&#xff0c;"会话"一般指的是Web服务器与客户端&#xff08;通常是浏览器&#xff09;之间进行的一系列请求和响应。它是一种在网络上模拟人与人之间通信的方式&#xff0c;常见于Web应用程序中。 会话、Cookie和Sessio…

Vue电商后端管理API接口测试

引言 最近有人在学习接口自动化测试时没有接口练手&#xff0c;其实接口的话&#xff0c;要么找第三方提供的&#xff0c;要么自己开发。第三方在线API需要认证&#xff0c;并且普通的话每天调用次数有一定的限制。自己开发的话&#xff0c;只要不停电&#xff0c;想怎么用就怎…

Jmeter接口自动化测试 :Jmeter变量的使用

在使用jmeter进行接口测试时&#xff0c;我们难免会遇到需要从上下文中获取测试数据的情况&#xff0c;这个时候就需要引入变量了。 定义变量 添加->配置元件->用户自定义的变量 添加->配置元件->CSV 数据文件设置 变量的调用方式&#xff1a;${变量名} 变量的作…

低代码平台的崛起:探索火爆背后的因素

文章目录 前言低代码开发平台优缺点有哪些&#xff1f;速度稳定性赋能一致性安全简单低代码为什么能火&#xff1f;由哪些因素导致&#xff1f; 低代码的优势后记 前言 在当前科技发展快速的时代&#xff0c;低代码开发平台越来越受到关注和推崇。与传统的软件开发方式相比&am…

C++学习笔记——类作用域和抽象数据类型

目录 一、C类作用域 类内作用域 类外作用域 二、类作用域案列详细的解释说明 三、抽象数据类型 四、总结 类作用域 抽象数据类型&#xff08;ADT&#xff09; 五、图书馆管理系统 一、C类作用域 在C中&#xff0c;类作用域是指类定义中声明的标识符&#xff08;成员变…

我建立了一个资源分享群

我建立了一个资源分享群 在为寻找资源犯愁&#xff1f; 在为分享资源犯愁&#xff1f; 一起加入分享资源群&#xff08;是wx群哦&#xff09;吧&#xff01;你可以分享自己的资源帮助他人。你可以在群组里需求资源获取别人的帮助。发广告请绕行&#xff0c;会被拉黑哦 微信…

基于SpringBoot+Vue人力资源管理系统(前后端分离)

该项目完全免费 系统介绍 基于 SpringBootVue 实现的人力资源管理系统是为了提高企业人力资源管理水平而开发的。主要目标是通过对员工 及人力资源活动信息&#xff08;考勤、工资 ) 等的编制来提高企业效率。 系统一共分为五大菜单项&#xff0c;分别是首页、薪资管理、权…

Linux安装nginx(带http ssl)

nginx安装 nginx文件 以及gcc pcre zlib openssl 网盘下载 1.安装gcc yum -y install gcc gcc-c 2.安装pcre rpm -ivh pcre-8.32-17.el7.x86_64.rpm --force --nodeps rpm -ivh pcre-devel-8.32-17.el7.x86_64.rpm --force --nodeps 3.安装zlib tar -zxvf zlib-1.2.11.ta…

Bayes贝叶斯识别Spam Email垃圾邮件

目录 介绍&#xff1a; 一、Gaussian Naive Bayes(连续型变量) 1.1数据处理 1.2建模 1.3cross_val_score函数评估 1.4classification_report函数评估 1.5classification_report函数和cross_val_score函数的区别 二、 Multinomial Naive Bayes&#xff08;离散型变量&…

【算法设计与分析】分治-时间复杂度计算

目录 主定理 Master Theorem分治算法运行时间的递归表示主定理的简化形式 主定理的一般形式 递归树 Recursion Tree递归树的简单结论 主定理 Master Theorem 分治算法运行时间的递归表示 将原问题分解成 a 个子问题递归求解&#xff0c;每个子问题的规模是原问题的 1/b。同时子…

紫光展锐5G扬帆出海 | 欧洲积极拥抱更多5G选择

和我国一样&#xff0c;欧洲不少国家也在2019年进入5G商用元年&#xff1a;英国在2019年5月推出了5G商用服务&#xff0c;该国最大的移动运营商EE(Everything Everywhere)最先商用5G&#xff1b;德国在2019年年中推出5G商用服务&#xff0c;德国电信、沃达丰和 Telefonica是首批…

从0开始python学习-42.requsts统一请求封装

统一请求封装的目的&#xff1a; 1.去除重复的冗余的代码 2. 跨py文件实现通过一个sess来自动关联有cookie关联的接口。 3. 设置统一的公共参数&#xff0c;统一的文件处理&#xff0c;统一的异常处理&#xff0c;统一的日志监控&#xff0c;统一的用例校验等 封装前原本代…

手写视频裁剪框

<!-- 截取框 --><divv-show"isShow"class"crop-box":style"{width: cropWidth px,height: cropHeight px,left: cropX px,top: cropY px,}"ref"cropBox"mousedown"startInteraction"><!-- 内容在这里 --…

Kubernetes二进制部署 单节点

一、环境准备 k8s集群master1&#xff1a;192.168.229.90 kube-apiserver kube-controller-manager kube-scheduler etcd k8s集群node1: 192.168.229.80 kubelet kube-proxy docker flannel k8s集群node2: 192.168.229.70 kubelet kube-proxy docker flannel 至少2C2G 常见的k…

软件工程:数据流图相关知识和多实例分析

目录 一、数据流图相关知识 1. 基本介绍 2. 常用符号 3. 附加符号 二、数据流图实例分析 1. 活期存取款业务处理系统 2. 工资计算系统 3. 商业自动化系统 4. 学校人事管理系统 5. 教材征订系统 6. 高考录取统分子系统 7. 订货系统 8. 培训中心管理系统 9. 考务处…

【动态规划】【字符串】C++算法:140单词拆分

作者推荐 【动态规划】【字符串】扰乱字符串 本文涉及的基础知识点 动态规划 字符串 LeetCode140:单词拆分 II 给定一个字符串 s 和一个字符串字典 wordDict &#xff0c;在字符串 s 中增加空格来构建一个句子&#xff0c;使得句子中所有的单词都在词典中。以任意顺序 返回…

PyTorch|一次画一批图像

想想这样一个场景&#xff0c;我们训练了一个神经网络&#xff0c;输入一些信息&#xff0c;这个网络可以根据信息为我们生成相关图片。 这些图片并不是一张&#xff0c;而是多张&#xff0c;我们想把这些图片一次全部显示出来&#xff0c;而不是一张一张的显示&#xff08;这…

【JAVA】异常体系

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; JAVA ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 Exception&#xff08;异常&#xff09;: Error: 结语 我的其他博客 前言 在Java编程中&#xff0c;异常处理是一个至关…