struct结构体内的对齐问题

2024-04-22 06:58

本文主要是介绍struct结构体内的对齐问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

truct结构体由于包含了不同的数据类型,而数据结构类型之间存在占用空间大小的问题,比如char型占用1字节,short int占用2字节,int、long int、指针、float占用4字节、double占用8字节(windows和linux中)。但计算机系统对基本数据类型可能允许地址做出了限制,要求某种类型的对象必须是2、4或8的倍数(为了简化处理器和存储系统之间的硬件设计——可以节省至少1根地址线)。


首先要说的几点是关于概念性的东西,现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始。但是,计算机在存储数据的时候,为了访问效率的考虑,在访问特定变量的时候经常在特定的内存访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。(参考百度百科)


如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐。如果机器的整型值长度为4个字节,假设一个整型变量的地址为0x00000008,那它就是自然对齐的。假设上面整型变量的地址不是自然对齐,比如为0x00000006,则CPU如果取它的值的话需要 访问两次内存,第一次取从0x00000006-0x00000007的两个字节,第二次取从0x00000008-0x00000009的两个字节。t然后组合得到所要的数据。如果变量在0x00000005地址上的话则要访问三次内存,第一次为一个字节,第二次为两个字节,第三次为一个字节,然后组合得到整型数据。而如果变量在自然对齐位置上,则只要一次就可以取出数据。

我们对齐的规则是:每个成员按其类型的大小和指定对齐参数(这里默认是8字节)中较小的一个对齐。并且结构的总长度必须为所用过的所有对齐参数的整数倍,不够就补空字节。

那么对于给出的一个struct类型数据,我们如何判断它占用多少空间呢?


C++ struct内存分配大小  


一  原则:  

1 所有字段在内存中出现顺序与声明顺序一致 (理论上,译器可以随便放置各个字段)  
2 由于性能原因,大多数编译器实际上会将struct 的各个字段对齐放置在合适的内存边界。具体细节随着语言编译器和CPU的不同而不同。在80X86体系中,符合Intel应用二进制接口(ABI  Application Bianry Interface)的编译器会将单字节对象分配在struct中任意偏移量处,字分配在字偏移量处,而双字或者更大的对象则分配在双字边界。  
3 大多数编译器会确保整个记录的长度是2、4或者8个字节的整数倍,他们通过在记录的末尾添加补齐字节以增加struct长度来做到这一点。编译器之所以要补齐struct的大小,是为了要确保记录的长度是记录中的最大纯量(Scalar)对象大小或者CPU的最优对齐大小的整数倍。  
4 通常编译器会提供一个选项,让你可以在全局上禁止这一功能。很多编译器还提供了pragma后者packed等关键字来让你能够逐struct地关掉字段对齐(优点是节省内存,缺点是增加了时间开销)  


二 C++数据类型大小  

char       1Byte  
short      2Byte  
int        4Byte  
long long  8Byte  
string     32Byte(空字符串,STL构造函数暂且将其大小置为32Byte)  


三 VS2008中struct大小遵循的原则:  

0 字段在内存中出现顺序与声明顺序一致(符合第1条)  
1 struct的长度是最长纯量的整数倍(符合第3条)  
2 struct大小符合ABI规则(符合第2条)  


四 例子  

    string t;  
    long long l;  
    int i;  
    char c;   
这个大小为48=32+8+4+4  
    long long l;  
    string t;  
    int i;  
    char c;  
这个大小为48=8+32+4+4  
int i;  
    long long l;  
    string t;  
    char c;  
这个大小为56=8+8+32+8  
    char c;  
    short s;  
    int i;  
    long long l;  
    string t;  
这个大小为 48=2+2+4+8+32  
    short a;  
    long long b;  
    char c;  
    short d;  
    int e;  
    short f;  
    long long g;  

这个真实大小为 2+8+1+2+4+2+8   实际是8+8+2+2+4+8+8=40;  


五 Reference  

《编程卓越之道 第一卷 深入理解计算机》Randall Hyde 张菲译

这篇关于struct结构体内的对齐问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/925091

相关文章

如何解决mmcv无法安装或安装之后报错问题

《如何解决mmcv无法安装或安装之后报错问题》:本文主要介绍如何解决mmcv无法安装或安装之后报错问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录mmcv无法安装或安装之后报错问题1.当我们运行YOwww.chinasem.cnLO时遇到2.找到下图所示这里3.

浅谈配置MMCV环境,解决报错,版本不匹配问题

《浅谈配置MMCV环境,解决报错,版本不匹配问题》:本文主要介绍浅谈配置MMCV环境,解决报错,版本不匹配问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录配置MMCV环境,解决报错,版本不匹配错误示例正确示例总结配置MMCV环境,解决报错,版本不匹配在col

Vue3使用router,params传参为空问题

《Vue3使用router,params传参为空问题》:本文主要介绍Vue3使用router,params传参为空问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录vue3使用China编程router,params传参为空1.使用query方式传参2.使用 Histo

SpringBoot首笔交易慢问题排查与优化方案

《SpringBoot首笔交易慢问题排查与优化方案》在我们的微服务项目中,遇到这样的问题:应用启动后,第一笔交易响应耗时高达4、5秒,而后续请求均能在毫秒级完成,这不仅触发监控告警,也极大影响了用户体... 目录问题背景排查步骤1. 日志分析2. 性能工具定位优化方案:提前预热各种资源1. Flowable

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

SpringBoot启动报错的11个高频问题排查与解决终极指南

《SpringBoot启动报错的11个高频问题排查与解决终极指南》这篇文章主要为大家详细介绍了SpringBoot启动报错的11个高频问题的排查与解决,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一... 目录1. 依赖冲突:NoSuchMethodError 的终极解法2. Bean注入失败:No qu

使用Java实现通用树形结构构建工具类

《使用Java实现通用树形结构构建工具类》这篇文章主要为大家详细介绍了如何使用Java实现通用树形结构构建工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录完整代码一、设计思想与核心功能二、核心实现原理1. 数据结构准备阶段2. 循环依赖检测算法3. 树形结构构建4. 搜索子

MySQL新增字段后Java实体未更新的潜在问题与解决方案

《MySQL新增字段后Java实体未更新的潜在问题与解决方案》在Java+MySQL的开发中,我们通常使用ORM框架来映射数据库表与Java对象,但有时候,数据库表结构变更(如新增字段)后,开发人员可... 目录引言1. 问题背景:数据库与 Java 实体不同步1.1 常见场景1.2 示例代码2. 不同操作

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

如何解决mysql出现Incorrect string value for column ‘表项‘ at row 1错误问题

《如何解决mysql出现Incorrectstringvalueforcolumn‘表项‘atrow1错误问题》:本文主要介绍如何解决mysql出现Incorrectstringv... 目录mysql出现Incorrect string value for column ‘表项‘ at row 1错误报错