内存对齐--面试常问问题和笔试常考问题
1.内存对齐的意义
C++ 内存对齐的主要意义可以简练概括为以下几点:
-
提高访问效率:内存对齐可以使数据在内存中以更加紧凑的方式存储,从而提高了数据的访问效率。处理器通常能够更快地访问内存中对齐的数据,而不需要额外的字节偏移计算。
-
硬件要求:许多硬件平台要求数据按照一定的对齐规则存储,否则可能会导致性能下降或者错误。不符合硬件要求的数据存储方式可能会引发总线错误或性能降低。
-
结构体和类的正确性:在C++中,结构体和类中的成员变量通常按照编译器的默认对齐方式进行排列,以确保数据的正确访问和存储。手动调整对齐方式可以保证数据的正确性。
-
跨平台开发:内存对齐可以确保数据在不同平台上的一致性。这对于跨平台开发非常重要,因为不同的硬件架构可能有不同的对齐要求。
-
节省内存:内存对齐可以减少内存碎片,从而节省内存空间。当数据按照对齐要求存储时,不会出现因为填充字节而浪费内存的情况。
总之,C++ 内存对齐的主要意义在于提高访问效率、符合硬件要求、确保数据的正确性、支持跨平台开发以及节省内存空间。通过遵循对齐规则,可以充分利用硬件的性能优势,并确保程序在不同平台上的可移植性和正确性。
2.对齐原则
原则1 :数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在
offiset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身
长度中,比较小的那个进行。(先偏移到那个对齐标准数的指定倍数,在进行加上本身)
原则2:结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进
行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的
那个进行。
原则3 :结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元
素大小的整数倍地址开始存储。
3.默认对齐值
默认对齐值:
Linux默认#pragma pack(4)
window默认#pragma pack(8)
注:可以通过预编译命令#pragma pack(n) , n=1,2,4,8,16来改变这一系数,其中的n就是指定
的“对齐系数”。
例题1:
#include <iostream>
#include <vector>
#include <algorithm>
#pragma pack(1)
using namespace std;struct AA
{int a; //长度4>1 按照1对齐,偏移量为0,存放位置区间[0,3]char b; //长度1==1 按1 对齐,偏移量为4,存放位置区间[4]short c; //长度2>1,按1对齐,偏移量提升到2的 倍数6,存放位置区间[5,6]char d; //长度1==1,按1 对齐,偏移量为6,存放位置区间[7]//整体存放【0-7】 位置中,共八个字节。
};int main()
{cout << sizeof(AA) << endl;system("pause");return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#pragma pack(2)
using namespace std;struct AA
{int a; //长度4>1 按照1对齐,偏移量为0,存放位置区间[0,3]char b; //长度1==1 按1 对齐,偏移量为4,存放位置区间[4]short c; //长度2>1,按1对齐,偏移量,存放位置区间[5,6]char d; //长度1==1,按1 对齐,偏移量为6,存放位置区间[7]//整体存放【0-7】 位置中,共八个字节。
};struct BB
{// BB 是注释掉以上 内容 按照2个字节对齐的情况int a; //长度4>2 按照2对齐,偏移量为0,存放位置区间[0,3]char b; //长度2>1 按1 对齐,偏移量为4,存放位置区间[4]short c; //长度2=1,按2对齐,整体偏移到2的倍数6,存放位置区间[6,7]char d; //长度2>1,按1对齐,偏移量为7,存放位置区间[8],共9个字节。//整体存放【0-8】 位置中,共9个字节。
};int main()
{// cout << sizeof(AA) << endl;cout << sizeof(BB) << endl;system("pause");return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#pragma pack(4)
using namespace std;struct AA
{int a; //长度4>1 按照1对齐,偏移量为0,存放位置区间[0,3]char b; //长度1==1 按1 对齐,偏移量为4,存放位置区间[4]short c; //长度2>1,按1对齐,偏移量,存放位置区间[5,6]char d; //长度1==1,按1 对齐,偏移量为6,存放位置区间[7]//整体存放【0-7】 位置中,共八个字节。
};struct BB
{// BB 是注释掉以上 内容 按照2个字节对齐的情况int a; //长度4>2 按照2对齐,偏移量为0,存放位置区间[0,3]char b; //长度2>1 按1 对齐,偏移量为4,存放位置区间[4]short c; //长度2=1,按2对齐,整体偏移到2的倍数6,存放位置区间[6,7]char d; //长度2>1,按1对齐,偏移量为7,存放位置区间[8],共9个字节。//整体存放【0-8】 位置中,共9个字节。
};struct CC
{int a; //长度4=4 按照4对齐,偏移量为0,存放位置区间[0,3]char b; //长度4>1 按照1对齐,偏移量为4,存放区间[4]short c; //长度 2<4 按照两个字节对齐,对齐到2的倍数6 存放位置{6,7}char d; // 1<4 ,按照1 对齐。偏移量为7.存放位置的区间为[8],总大小为9
};int main()
{// cout << sizeof(AA) << endl;// cout << sizeof(BB) << endl;cout << sizeof(CC) << endl;system("pause");return 0;
}


8字节对齐
#include <iostream>
#include <vector>
#include <algorithm>
#pragma pack(8)
using namespace std;struct AA
{int a; //长度4>1 按照1对齐,偏移量为0,存放位置区间[0,3]char b; //长度1==1 按1 对齐,偏移量为4,存放位置区间[4]short c; //长度2>1,按1对齐,偏移量,存放位置区间[5,6]char d; //长度1==1,按1 对齐,偏移量为6,存放位置区间[7]//整体存放【0-7】 位置中,共八个字节。
};struct BB
{// BB 是注释掉以上 内容 按照2个字节对齐的情况int a; //长度4>2 按照2对齐,偏移量为0,存放位置区间[0,3]char b; //长度2>1 按1 对齐,偏移量为4,存放位置区间[4]short c; //长度2=1,按2对齐,整体偏移到2的倍数6,存放位置区间[6,7]char d; //长度2>1,按1对齐,偏移量为7,存放位置区间[8],共9个字节。//整体存放【0-8】 位置中,共9个字节。
};struct CC
{int a; //长度4=4 按照4对齐,偏移量为0,存放位置区间[0,3]char b; //长度4>1 按照1对齐,偏移量为4,存放区间[4]short c; //长度 2<4 按照两个字节对齐,对齐到2的倍数6 存放位置{6,7}char d; // 1<4 ,按照1 对齐。偏移量为7.存放位置的区间为[8],总大小为9
};struct DD
{int a; // 4<8 按4对齐, 偏移:0 位置 {0,3}char b; // 1<8 按1对齐 偏移:4 位置:{4}short c; // 2<8 按照2 对齐 偏移 6 位置 {6,7}char d; // 1<8 按照1 对齐 偏移为7 位置[8] 总大小为9
};int main()
{// cout << sizeof(AA) << endl;// cout << sizeof(BB) << endl;// cout << sizeof(CC) << endl;cout << sizeof(DD) << endl;system("pause");return 0;
}


#按照8位,有 包含 double的情况。
#include <iostream>
#include <vector>
#include <algorithm>
#pragma pack(8)
#include <stddef.h>
using namespace std;struct AA
{int a; //长度4>1 按照1对齐,偏移量为0,存放位置区间[0,3]char b; //长度1==1 按1 对齐,偏移量为4,存放位置区间[4]short c; //长度2>1,按1对齐,偏移量,存放位置区间[5,6]char d; //长度1==1,按1 对齐,偏移量为6,存放位置区间[7]//整体存放【0-7】 位置中,共八个字节。
};struct BB
{// BB 是注释掉以上 内容 按照2个字节对齐的情况int a; //长度4>2 按照2对齐,偏移量为0,存放位置区间[0,3]char b; //长度2>1 按1 对齐,偏移量为4,存放位置区间[4]short c; //长度2=1,按2对齐,整体偏移到2的倍数6,存放位置区间[6,7]char d; //长度2>1,按1对齐,偏移量为7,存放位置区间[8],共9个字节。//整体存放【0-8】 位置中,共9个字节。
};struct CC
{int a; //长度4=4 按照4对齐,偏移量为0,存放位置区间[0,3]char b; //长度4>1 按照1对齐,偏移量为4,存放区间[4]short c; //长度 2<4 按照两个字节对齐,对齐到2的倍数6 存放位置{6,7}char d; // 1<4 ,按照1 对齐。偏移量为7.存放位置的区间为[8],总大小为9
};struct DD
{int a; // 4<8 按4对齐, 偏移:0 位置 {0,3}char b; // 1<8 按1对齐 偏移:4 位置:{4}short c; // 2<8 按照2 对齐 偏移 6 位置 {6,7}char d; // 1<8 按照1 对齐 偏移为7 位置[8] 总大小为9
};struct EE
{int a; // 4<8 按4对齐, 偏移:0 位置 {0,3}double b; // 8==8 按8对齐 偏移量偏移到8的倍数 偏移8 位置:{8,16}short c; // 2<8 按照2 对齐 偏移 16 位置 {16,17}char d; // 1<8 按照1 对齐 偏移为17 位置[18] 总大小为9
};int main()
{// cout << sizeof(AA) << endl;// cout << sizeof(BB) << endl;// cout << sizeof(CC) << endl;// cout << sizeof(DD) << endl;cout << sizeof(EE) << endl;cout << offsetof(EE, b) << endl; //查看偏移了多少内存。system("pause");return 0;
}

例四:结构体包含结构体的运算。
#include <iostream>
#include <vector>
#include <algorithm>
#pragma pack(8)
#include <stddef.h>
using namespace std;struct AA
{int a; //长度4>1 按照1对齐,偏移量为0,存放位置区间[0,3]char b; //长度1==1 按1 对齐,偏移量为4,存放位置区间[4]short c; //长度2>1,按1对齐,偏移量,存放位置区间[5,6]char d; //长度1==1,按1 对齐,偏移量为6,存放位置区间[7]//整体存放【0-7】 位置中,共八个字节。
};struct BB
{// BB 是注释掉以上 内容 按照2个字节对齐的情况int a; //长度4>2 按照2对齐,偏移量为0,存放位置区间[0,3]char b; //长度2>1 按1 对齐,偏移量为4,存放位置区间[4]short c; //长度2=1,按2对齐,整体偏移到2的倍数6,存放位置区间[6,7]char d; //长度2>1,按1对齐,偏移量为7,存放位置区间[8],共9个字节。//整体存放【0-8】 位置中,共9个字节。
};struct CC
{int a; //长度4=4 按照4对齐,偏移量为0,存放位置区间[0,3]char b; //长度4>1 按照1对齐,偏移量为4,存放区间[4]short c; //长度 2<4 按照两个字节对齐,对齐到2的倍数6 存放位置{6,7}char d; // 1<4 ,按照1 对齐。偏移量为7.存放位置的区间为[8],总大小为9
};struct DD
{int a; // 4<8 按4对齐, 偏移:0 位置 {0,3}char b; // 1<8 按1对齐 偏移:4 位置:{4}short c; // 2<8 按照2 对齐 偏移 6 位置 {6,7}char d; // 1<8 按照1 对齐 偏移为7 位置[8] 总大小为9
};struct EE
{int a; // 4<8 按4对齐, 偏移:0 位置 {0,3}double b; // 8==8 按8对齐 偏移量偏移到8的倍数 偏移8 位置:{8,16}short c; // 2<8 按照2 对齐 偏移 16 位置 {16,17}char d; // 1<8 按照1 对齐 偏移为17 位置[18] 总大小为9
};//=============================================================
struct GG
{//结构体内部最大元素为int.由于偏移量8刚好是4 的倍数,所以从8 开始存放struct 对应了规则三。int a1; // 4<8 4 8 [8,11]char b1; // 1<8 1 12 [12]short c1; // 2<8 2 14 [14,15]char d1; // 1 <8 1 16 [16]
};
struct FF
{int a; // 4<8 按4 偏移0 存放的位置【0,3】char b; // 1<8 按1 偏移4 [4]short c; // 2<8 2 6 [6,7]GG g;//子strcut整体对齐系数=min((max(int,short,char),8))=4. 将内存补齐到4 的整数倍 20.char d; // 1<8 1 21 21//整体对齐系数 4 所有有21 补到24.
};
//===========================================
int main()
{// cout << sizeof(AA) << endl;// cout << sizeof(BB) << endl;// cout << sizeof(CC) << endl;// cout << sizeof(DD) << endl;// cout << sizeof(EE) << endl;// cout << offsetof(EE, b) << endl; //查看偏移了多少内存。cout << sizeof(FF) << endl;// cout << offsetof(FF, GG) << endl;system("pause");return 0;
}



4.练习:
#include <iostream>
#include <vector>
#include <algorithm>
#pragma pack(8)
using namespace std;struct A
{int a; // [0,4]double b;// [ 8, 16 ]float c;// [ 17, 20 ]
};
// #24struct B
{char e[2]; // 1<8 按照2对齐 偏移 0 位置【0,1】short h; // 2<8 2 2 [2,4]A a; // 24// 一共28 偏移一起达到32.
};int main()
{cout << sizeof(B) << endl;system("pause");return 0;
}



相关文章:
内存对齐--面试常问问题和笔试常考问题
1.内存对齐的意义 C 内存对齐的主要意义可以简练概括为以下几点: 提高访问效率:内存对齐可以使数据在内存中以更加紧凑的方式存储,从而提高了数据的访问效率。处理器通常能够更快地访问内存中对齐的数据,而不需要额外的字节偏移计…...
贪心算法-会议室问题
1、题目描述 一些项目要占用一个会议室宣讲,会议室不能同时容纳两个项目。现在给你两个长度一样的数组,starts数组代码每个会议开始的时间,ends数组代表每个会议结束的时间。 在给你一个当前时间,请你求出当日可以利用会议室宣讲的…...
单日 5000 亿行 / 900G 数据接入,TDengine 3.0 在中国地震台网中心的大型应用
小T导读:为满足地震预警数据存储、检索和处理的建设与集成需求,以及响应国家国产软件自主可控的号召,中国地震台网中心决定选用国产数据库 TDengine 来存储和处理地震波形数据。本文将针对 TDengine 3.0 在地震领域的应用展开详细讲解。 关于…...
【VIM系列】cscope命令
cscope...
Vue的自定义事件(Custom Events):实现组件间通信的强大工具
Vue的自定义事件(Custom Events):实现组件间通信的强大工具 Vue.js是一款流行的JavaScript框架,用于构建交互式的Web应用程序。在Vue中,组件是构建应用程序的基本单元,它们之间的通信对于构建复杂的应用非…...
简易实现通讯录(1.0)
前言 我们还是像以前一样,分为三个文件来书写,分别是contact.h,contact.c,test.c 分别用来声明函数,实现函数和测试函数功能,现在就让我们开始吧. 1.基本逻辑 首先我们定义通讯录里的数据,我们定义为结构体 typedef struct PeoInfo {char name[NAME_MAX];int age;char sex[SEX_…...
CSS笔记——触发式动画Transition、主动式动画Animation、Transfrom 动画、CSS 3D 动画、阴影和滤镜样式
CSS动画 一、触发式动画Transition transition过渡动画,一般配合伪类使用 属性值: transition-duration: 指定过渡效果的持续时间,以秒或毫秒为单位。 transition-timing-function: 指定过渡效果的时间函数ÿ…...
软件测试之Web安全测试详解
前言 随着互联网时代的蓬勃发展,基于Web环境下的应用系统、应用软件也得到了越来越广泛的使用。 目前,很多企业的业务发展都依赖于互联网,比如,网上银行、网络购物、网络游戏等。但,由于很多恶意攻击者想通过截获他人…...
MYSQL binlog
为了防止 binlog 文件过大导致无可用的磁盘空间,MySQL 提供了一个系统变量用来配置过期时间。 MySQL5.7 :expire_logs_days,精确度为天; MySQL8.0 :binlog_expire_logs_seconds,精确度为秒。 SET GLOBAL bi…...
Web 基础概念
自己总结的web前端知识体系大全 基础概念 DOM DOM是什么意思-前端入门_dom是什么意思啊_猿说前端的博客-CSDN博客 DOM的含义: DOM称为文件对象模型(DocumentObjectModel,简称DOM),是W3C组织推荐的处理可扩展置标语言的…...
谈谈最近招人的感受!
最近折腾新的项目,面试了很多实习生小伙伴,我说说我的一些「面试」感受, 虽然是一个老生常谈的话题,但是依然提一下。 准时很重要:提前一点时间,踩个点,别迟到,面试的过程中由于每个…...
【日常业务开发】Java调用第三方http接口的常用方式
【日常业务开发】Java调用第三方http接口的常用方式 概述Java调用第三方http接口的方式通过JDK网络类Java.net.HttpURLConnection通过apache common封装好的HttpClient通过Apache封装好的CloseableHttpClient通过OkHttp通过Spring的RestTemplate通过hutool的HttpUtil 总结 概述…...
【大数据开发技术】实验04-HDFS文件创建与写入
文章目录 一、实验目标二、实验要求三、实验内容四、实验步骤 一、实验目标 熟练掌握hadoop操作指令及HDFS命令行接口掌握HDFS原理熟练掌握HDFS的API使用方法掌握单个本地文件写入到HDFS文件的方法掌握多个本地文件批量写入到HDFS文件的方法 二、实验要求 给出主要实验步骤成…...
中国制造让苹果跪服,将再增加一家中国高科技供应商
日前产业链人士指出由于京东方的OLED面板有力地制衡韩国面板厂商三星和LGD,促使他们降价,而且技术也不错,因此正计划再引入一家中国OLED面板厂商,以进一步促进OLED面板的竞争。 早期苹果的OLED面板完全由三星供应,由此…...
港卡开户感想(2023-8)
目录 银行列表预约开户总体原则外资行本地行内资行补充 选择落地点酒店及转换插头国际漫游换港币成行下一步 - 保险附录整理的银行资料 2023年8月份去了趟香港做银行开户, 整理如下供参考. 银行列表 https://www.hkma.gov.hk/gb_chi/smart-consumers/account-opening/contact-…...
机器学习第十一课--K-Means聚类
一.聚类的概念 K-Means算法是最经典的聚类算法,几乎所有的聚类分析场景,你都可以使用K-Means,而且在营销场景上,它就是"King",所以不管从事数据分析师甚至是AI工程师,不知道K-Means是”不可原谅…...
Java on Azure Tooling 8月更新|以应用程序为中心的视图支持及 Azure 应用服务部署状态改进
作者:Jialuo Gan - Program Manager, Developer Division at Microsoft 排版:Alan Wang 大家好,欢迎阅读 Java on Azure 工具的八月更新。在本次更新中,我们将推出新的以应用程序为中心的视图支持,帮助开发人员在一个项…...
论文笔记:ST2Vec: Spatio-Temporal Trajectory SimilarityLearning in Road Networks
2022 KDD 1 intro 现有的轨迹相似性学习方案强调空间相似性而忽视了时空轨迹的时间维度,这使得它们在有时间感知的场景中效率低下 如上图,在拼车过程中,T1表示司机计划的行程,T2和T3是两个想要搭车的人。T1和T2在空间上更接近&am…...
upload-labs靶场未知后缀名解析漏洞
upload-labs靶场未知后缀名解析漏洞 版本影响: phpstudy 版本:5.2.17 1 环境搭建 1.1 在线靶场下载,解压到phpstudy的www目录下,即可使用 https://github.com/c0ny1/upload-labs1.2 已启动:访问端口9000&…...
VisualStudio配置opencv
下载opencv 链接:https://opencv.org/releases/ 我下载的是4.7.0,选择windows下载。 下载成功后打开exe文件,选择路径安装。 配置环境变量 安装成功后找到安装目录,复制bin目录路径。 我的是放在了D盘 D:\Opencv4.7.0\opencv…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
