最新要闻
- vivo X Flip登场:航空级铝合金中框 3英寸超大外屏
- 全球首个12.1寸7:5大屏 vivo Pad2屏幕大升级:拒绝低成本_全球观点
- 【世界独家】最强火箭SpaceX星舰今晚重新发射!现场大雾弥漫:又要延期?
- 快播:首发2399元起 vivo Pad2平板发布:娱乐与生产力双旗舰
- 时隔10年 新一代PC硬件杀手:《孤岛危机4》来了
- 马布里发微博:篮球之神是公平的
- 安装到c盘和d盘的区别 c盘和d盘的区别
- 业绩亏损的股票有可能上涨吗?股票的涨跌原理
- 每日热点:中汽协:3月乘用车产销分别完成214.9万辆和201.7万辆 同比分别增长14.3%和8.2%
- 铜川市气象台发布沙尘暴黄色预警【Ⅲ级/较重】
- 环球热头条丨最强折叠屏!vivo X Fold2亮相:7项参数全球唯一
- 《古龙风云录》等86款游戏过审:4月国产游戏版号公布
- 《灌篮高手》周边卖断货 官方急挂公告:真没货了 亲们!_世界头条
- 全球最资讯丨科大讯飞Q1营收28.88亿元 即将发布认知大模型
- vivo X Fold2外观正式揭晓:双材质拼接设计独特 环球热资讯
- 快看点丨后悔没早学 两招轻松搞定打印机堵头难题
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
快讯:C++ 结构体对齐
C++ 结构体对齐
引言
数据结构对齐是数据在计算机内存中排列和访问的方式。它由三个独立但相关的问题组成:数据对齐、数据结构填充和打包。现代计算机硬件中的 CPU 在数据自然对齐时最有效地执行内存读取和写入,这通常意味着数据的内存地址是数据大小的倍数。例如,在 32 位架构中,如果数据存储在四个连续字节中并且第一个字节位于4字节边界上,则数据可能是对齐的。
数据对齐是根据元素的自然对齐方式对齐元素。为了确保自然对齐,可能需要在结构元素之间或结构的最后一个元素之后插入一些填充。例如,在 32 位机器上,包含一个 16 位值后跟一个 32 位值的数据结构可以在 16 位值和 32 位值之间有 16 位填充以对齐 32 位值32 位边界上的值。或者,可以打包结构,省略填充,这可能会导致访问速度变慢,但会使用四分之三的内存。
【资料图】
尽管数据结构对齐是所有现代计算机的基本问题,但许多计算机语言和计算机语言实现会自动处理数据对齐。 Fortran、Ada、PL/I、Pascal、某些 C 和 C++ 实现、D、Rust、C#、和汇编语言至少允许部分控制数据结构填充,这在某些特殊情况下可能很有用。
如何计算填充
这里以64位操作系统为例,首先我们列出一些基本类型的对其大小。
类型 | 对齐大小 |
---|---|
char(1byte) | 1 |
short(2bytes) | 2 |
long(4bytes) | 4 |
float(4bytes) | 4 |
double(8bytes) | 8 |
long double(8bytes) | 8 |
以long类型为例,long的对齐大小为4,代表着这个类型的地址应该可以被4所整除,也就是其二进制地址应该是以0b100结尾。同理,short就是以0b10结尾,double就是以0b1000结尾。需要注意的是对齐大小都是2的整数次幂。
int main(int argc, char const *argv[]){ static_assert(alignof(long) == 4); alignas(4) long x; std::bitset<64> address = (uint64_t)std::addressof(x); // 0000000000000000000000000111001010111111010111111111101100111100 std::cout << address.to_string() << "\n"; return 0; }
知道了基础类型之后,我们来看结构体的类型:
struct F1{ // alignment sizeof int8_t i8; // 1 1 int16_t i16; // 2 2 double f64; // 8 8};static_assert(alignof(F1) == 8);static_assert(sizeof(F1) == 16);
1、如何计算对齐大小?
结构体类型的对齐大小为最大的成员字段的对齐大小,F1结构体中f64字段对齐大小是最大的,所以F1的对齐大小和double保持一致。
2、如何计算结构体大小
int main(int argc, char const *argv[]){ alignas(8) F1 f; std::bitset<64> address; // 0b000000 address = (uint64_t)std::addressof(f); std::cout << address.to_string() << "\n"; // 0b000000 address = (uint64_t)std::addressof(f.i8); std::cout << address.to_string() << "\n"; // 0b000010 address = (uint64_t)std::addressof(f.i16); std::cout << address.to_string() << "\n"; // 0b001000 address = (uint64_t)std::addressof(f.f64); std::cout << address.to_string() << "\n"; return 0; }
我们将f及其所有字段的地址的最后6比特打印出来。由于f是按照8字节对齐,所以f的二进制地址最后应该是0b1000结尾。i8是按照1字节对齐,它是结构体的第一个字段,其地址和f地址一样。i16是按照2字节对齐的,所以他的地址应该是以0b100结尾,而f的地址0b000000在安放完一个i8后的下一个以0b100结尾的地址是0b000010,所以i16会被安放在0b000010。f64是按照8字节对齐,而f的地址0b000000在安放完一个i8和一个i16后的下一个以0b1000结尾的地址是0b001000,所以f64会被安放在0b001000,如图所示:
模拟布局
为了更好地了解结构体的内存布局,接下来我们来模拟一下。
template struct layout_impl;template struct layout_impl, std::index_sequence>{ // ...};// Ts... 是我们结构体每一个字段的类型template struct layout : layout_impl< std::tuple, std::make_index_sequence>{};
首先是构造函数,我们使用一个数组来记录每个字段的数量,在构造时提供每个字段的数量即可。
template struct layout_impl, std::index_sequence>{ // C++目前不允许layout_impl(size_t... sizes)这种写法,我们利用模板来完成这个功能 constexpr explicit layout_impl(detail::to_size_t... sizes) : m_sizes{ sizes... } {} std::array m_sizes;};/*struct F1{ int8_t i8; int16_t i16; double f64; }; => layout(1, 1, 1)struct TreeNode{ int value; TreeNode* children[2];}; => layout(1, 2);*/
其次是结构体的对齐大小,结构体的对齐大小和对齐大小最大的那个字段保持一致。
static constexpr size_t alignment() { return std::ranges::max({ alignof(Ts)... });}
再然后是计算每一个字段的offset。
在计算某个字段的时候,我们需要知道上一个字段的offset和size,然后按照当前字段的对齐大小进行对齐。以F1的第二个字段i16为例,上一个字段是i8,由于他是第一个字段,offset为0,size是1个字节,我们可以按照如下公式计算:
\[ next = (current + align - 1) \mod align\]举个例子,假设我们是十进制并且按照10字节对齐,当前面有1个字节被占用的时候,我们需要填充9个字节,当前面有2个字节被占用的时候,我们需要填充8个字节,依次类推,当前面有10个字节都被占用的时候,我们不需要填充字节。
constexpr size_t align(size_t n, size_t m) { assert(std::popcount(m) == 1 && "m should be power of two."); return (n + m - 1) & ~(m - 1); }template constexpr size_t offset() const{ static_assert(N < NumSizes); if constexpr (N == 0) { return 0; } else { const auto last_type_size = sizeof(std::tuple_element_t>); const auto current_type_alignment = alignof(std::tuple_element_t>); return detail::align(offset() + last_type_size * m_sizes[N - 1], current_type_alignment); }}
最后是结构体的大小。我们只需要知道最后一个字段的offset,大小以及填充字节大小就可以了,需要注意的是,最后一个字节也是可能会填充的,这样在申请数组的时候才能保证每一个元素都是对齐的。
constexpr size_t alloc_size() const{ return offset() + sizeof(std::tuple_element_t>) * m_sizes[NumTypes - 1];}
题外话
结构体的字段的分布对布局是有影响的,如果我们更改F1字段的顺序,那么它的大小可能会发生变化。
struct F2{ // alignment sizeof int8_t i8; // 1 1 double f64; // 8 int16_t i16; // 2 2};static_assert(alignof(F2) == 8);static_assert(sizeof(F2) == 24);
如果您想更好地回顾关于结构体对齐的知识,可以参见https://www.youtube.com/watch?v=SShSV_iV1Ko。
参考文献
[1]维基百科:https://en.wikipedia.org/wiki/Data_structure_alignment
关键词:
微信小程序学习笔记 播报
无凭证条件下的权限获取
快讯:C++ 结构体对齐
债市日报:4月20日
vivo X Flip登场:航空级铝合金中框 3英寸超大外屏
全球首个12.1寸7:5大屏 vivo Pad2屏幕大升级:拒绝低成本_全球观点
【世界独家】最强火箭SpaceX星舰今晚重新发射!现场大雾弥漫:又要延期?
快播:首发2399元起 vivo Pad2平板发布:娱乐与生产力双旗舰
时隔10年 新一代PC硬件杀手:《孤岛危机4》来了
马布里发微博:篮球之神是公平的
安装到c盘和d盘的区别 c盘和d盘的区别
业绩亏损的股票有可能上涨吗?股票的涨跌原理
ASP.NET Core MVC 从入门到精通之wwwroot和客户端库 世界短讯
海思Hi35xx uboot启动分析总结
上平台! 车联网智能化晋级高段位!
PHP 教程_编程入门自学教程_菜鸟教程-免费教程分享-每日快讯
每日热点:中汽协:3月乘用车产销分别完成214.9万辆和201.7万辆 同比分别增长14.3%和8.2%
铜川市气象台发布沙尘暴黄色预警【Ⅲ级/较重】
环球热头条丨最强折叠屏!vivo X Fold2亮相:7项参数全球唯一
《古龙风云录》等86款游戏过审:4月国产游戏版号公布
《灌篮高手》周边卖断货 官方急挂公告:真没货了 亲们!_世界头条
全球最资讯丨科大讯飞Q1营收28.88亿元 即将发布认知大模型
vivo X Fold2外观正式揭晓:双材质拼接设计独特 环球热资讯
世界微速讯:【金融街发布】人民银行:加快新型信息基础设施建设 加快金融数字化转型
快看点丨后悔没早学 两招轻松搞定打印机堵头难题
全球微动态丨冰淇淋只给外国人道歉后 探访风波中的宝马mini展台:有男子免费派发甜筒
上海车展三星推第6代方形电池 UP主吐槽“闲人免进”:护我安全
天天时讯:家用强力灭蚊!雅格充电电蚊拍9.9元起抄底
巨幕大于想象!vivo X Fold2/X Flip折叠屏未发先火:超50万人预约
【天天速看料】2.56万方!南通这里,即将拆除!
环球微头条丨【0基础学爬虫】爬虫基础之自动化工具 Selenium 的使用
焦点精选!易基因:MeRIP-seq等揭示m6A甲基化修饰对抗病毒基因表达的转录调控机制|Cell Rep
关注:深度学习--PyTorch维度变换、自动拓展、合并与分割
【环球新要闻】记录-JS简单实现购物车图片局部放大预览效果
创建本地yum仓库
【世界报资讯】何冰:演员没有理解力就只剩大声说话了
合金弹头觉醒前期最强阵容搭配推荐
【天天热闻】4999元 机械师推出新款创物者X14笔电:RTX2050 4GB独显
当前热讯:小米13/13 Pro/13 Ultra三款机型对比:到底怎么选 一目了然
【快播报】暴雪承认《暗黑破坏神4》洗点费用有点贵 但不会改
沙尘翻过秦岭入川:局地AQI爆表!成都“躲过一劫”
天天短讯!雷军现身比亚迪腾势、仰望展台 用小米13 Ultra狂拍
世界热门:工信部:将实施5G规模化应用工程 指导发布5G行业建设指南
全球时讯:最新持仓浮出水面:百亿级私募左手AI右手“央国企”
【天天播资讯】Natasha Preheating(三)
全球新动态:集合 第二天
环球今热点:24道Python面试练习题
Kubesphere-DevOps-记一次流水线排错
新起点!大数据分布式可视化的 DAG 任务调度系统 Taier 正式发布1.4版本
滚动:蛇怕什么?
环球速递!小米之家人山人海!小米13 Ultra销售火爆
今日热搜:广告内容“量身定制”!谷歌计划使用生成式AI推送广告
天天热门:女子眼球被摘除,竟是痔疮惹的祸!
疯狂育儿模式 长达4年半不吃不喝不挪窝:自虐死亡的章鱼图啥?
瑞幸咖啡员工称被罚抄写顾客差评 客服回应:对顾客负责
天天观察:AMD YES!史上最强核显Radeon 780M首测:《赛博朋克2077》流畅丝滑
当前观察:2023年医保新规如何给家人用?医保卡新规2023一家人用可以吗?
全球短讯!k8s介绍与常用命令
我替 OpenAI 实现了 ChatGPT 聊天记录复制功能
天天讯息:ubuntu编译字符设备
今日热门!咨询chatGPT关于c#脚本的方案,全文无任何修改。
天天通讯!GIS在电力管理中的应用
央行:我国不存在长期通缩或通胀的基础
观焦点:新华社权威快报|5G基站超264万个 我国数字化基础不断夯实
天天微动态丨汽车厂商要登月!现代联手科研机构开发探月机器人
当前播报:俄罗斯开发者拿到钱了 显卡超频神器Afterburner恢复更新:等了1年半
环球热消息:斯柯达研发新EA211系列发动机:全新帕萨特、速派等50车搭载
人类最强火箭!SpaceX星舰今晚重新发射:目前系统一切正常
天天热议:宝马MINI的冰淇淋只配老外吃:高管刚表示BMW家在中国
“零工市场”为灵活就业“添翼续航”
“4.5%”彰显中国经济的韧性和活力
“中国车企加速迈向电动化,将国际老牌车企甩在身后”
环球新动态:IDEA编译Spring源码教程
微资讯!使用etcd实现Master的选举功能
Rust 知识积累(6)
当前快播:【Jmeter】Request1输出作为Request2输入-后置处理器
世界热文:详解数据结构中栈的定义和操作
通讯!估值1000亿 消息称国产内存厂商寻求IPO上市:4年前量产首款DDR4芯片
张颂文用小米13 Ultra拍照!网友建议加上水印
【天天时快讯】巴西总统认为电子游戏是垃圾 让年轻人学会暴力杀戮
长达10年维护落幕:微软提醒Office 2013已停止支持
当前速看:郑渊洁称维权生活像吃苍蝇:21年只成功37个商标 还有673个没成
联想刘军:今年将是大客户市场的 “大年”
浑厚悠扬!三号楼的钟声……
每日热议!房玄龄杜如晦被谁重用_房玄龄杜如晦
全球快资讯:springboot 中使用 RabbitMQ 配置使用优先级队列
查看Unity3D中默认的变量名与按键的映射
时隔6年后,我又回到博客园了
环球看点!更新整理了一大波热门免费可用的API大全
微动态丨ChatGPT闲谈——火出圈的为什么是 OpenAI?
新消息丨微软苏菲要换代了!Surface Pro 10/Go 4新品曝光:外形/配置大变
【环球报资讯】最新研究:黄河上游区域性干旱能“算来”
这个火车站客流暴增,原因竟是……
全球信息:雪莲子的功效与副作用 雪莲子的功效与作用及食用方法
世界播报:真我11系列拍摄样张首秀:长焦恐怖 可见月亮纹理
【热闻】没人比我更懂外星人?马斯克:如果找到外星人 我立马发推
环球热资讯!ZV-E10同款传感器:索尼FX10视频机即将发布
环球快资讯:熊孩子躲袋子里玩误被司机碾压 路人合力抬车救援:网友吐槽家长心大
环球速看:一大众轿车高速路恶意别车!S形行驶10公里:官方已介入调查
每日焦点!诺诚健华宣布奥布替尼成为中国首个且唯一获批针对边缘区淋巴瘤的BTK抑制剂