结构体字节对齐
2015-07-01 09:20
363 查看
在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何 变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际上访问特定类型的变量只能在特定的地址访问,这就需要各个变量在空间上按一定的规则排列, 而不是简单地顺序排列,这就是内存对齐。
内存对齐的原因:
1)某些平台只能在特定的地址处访问特定类型的数据;
2)提高存取数据的速度。比如有的平台每次都是从偶地址处读取数据,对于一个int型的变量,若从偶地址单元处存放,则只需一个读取周期即可读取该变量;但是若从奇地址单元处存放,则需要2个读取周期读取该变量。
win32平台下的微软C编译器对齐策略:
1)结构体变量的首地址能够被其最宽数据类型成员的大小整除。编译器在为结构体变量开辟空间时,首先找到结构体中最宽的数据类型,然后寻找内存地址能被该数据类型大小整除的位置,这个位置作为结构体变量的首地址。而将最宽数据类型的大小作为对齐标准。
2)结构体每个成员相对结构体首地址的偏移量(offset)都是每个成员本身大小的整数倍,如有需要会在成员之间填充字节。编译器在为结构体成员开辟空 间时,首先检查预开辟空间的地址相对于结构体首地址的偏移量是否为该成员大小的整数倍,若是,则存放该成员;若不是,则填充若干字节,以达到整数倍的要 求。
3)结构体变量所占空间的大小必定是最宽数据类型大小的整数倍。如有需要会在最后一个成员末尾填充若干字节使得所占空间大小是最宽数据类型大小的整数倍。
下面看一下sizeof在计算结构体大小的时候具体是怎样计算的
1.test1 空结构体
在C++中占1字节,而在C中占0字节。
2.test2
|--------int--------| 4字节
|char|----|--short-| 4字节
总共占8字节
3.test3
|char|----|----|----| 4字节
|--------int--------| 4字节
|--short--|----|----| 4字节
总共占12个字节
4.test4 含有静态数据成员
|--------int--------| 4字节
|--short-|----|----| 4字节
而变量c是单独存放在静态数据区的,因此用siezof计算其大小时没有将c所占的空间计算进来。
5.test5 结构体中含有结构体
|-------bool--------| 4字节
|-------s1----------| 8字节
|-------short-------| 4字节
6.test6
|--------bool--------| 8字节
|---------s1---------| 8字节
|--------double------| 8字节
|----int----|---------| 8字节
7.test7
若在程序中使用了#pragma pack(n)命令强制以n字节对齐时,默认情况下n为8.
则比较n和结构体中最长数据类型所占的字节大小,取两者中小的一个作为对齐标准。
若需取消强制对齐方式,则可用命令#pragma pack()
如果在程序开头使用命令#pragma pack(4),对于下面的结构体
|-----------a--------| 4字节
|--------s1----------| 4字节
|--------s1----------| 4字节
|--------b-----------| 4字节
|--------b-----------| 4字节
|---------c----------| 4字节
总结一下,在计算sizeof时主要注意一下几点:
1)若为空结构体,则只占1个字节的单元
2)若结构体中所有数据类型都相同,则其所占空间为 成员数据类型长度×成员个数
若结构体中数据类型不同,则取最长数据类型成员所占的空间为对齐标准,数据成员包含另一个结构体变量t的话,则取t中最 长数据类型与其他数据成员比较,取最长的作为对齐标准,但是t存放时看做一个单位存放,只需看其他成员即可。
3)若使用了#pragma pack(n)命令强制对齐标准,则取n和结构体中最长数据类型占的字节数两者之中的小者作为对齐标准。
另外除了结构体中存在对齐之外,普通的变量存储也存在字节对齐的情况,即自身对齐。编译器规定:普通变量的存储首地址必须能被该变量的数据类型宽度整除。
测试程序:
?
相关文章推荐
- 织梦登录后台,提示验证码不正确
- jenkins自动化部署脚本
- JS 数据类型转换
- JS模块加载器加载原理是怎么样的?
- java jdbc 连接 class.forname("driver")
- 顶级Javascript图表图形类库
- java中进行高精度、大数运算总结BigInteger BigDecimal
- 数据结构--二叉堆、d堆、左式堆和斜堆
- CSS经验
- android Vibrator 使用
- 设计模式之享元模式——初学
- C++常用库函数
- android中src和background区别
- C#下查找并杀死子进程(进程树)
- Jmeter插件JMeterPlugins
- gRPC:Google开源的基于HTTP/2和ProtoBuf的通用RPC框架
- leetcode_Valid Sudoku
- 织梦搜索时间间隔的修改方法
- 0-9、a-z、A-Z 随机数
- 装系统出现error cannot load file code 5555h 该如何解决