windows下结构体的数据对齐
2011-08-09 16:29
204 查看
前言
比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该int数据。数据对齐(Data Alignment) 这个要求可以提高存储器系统的性能,减少寻址次数,代价是浪费了一些空间。换句话说是用相对廉价的空间换得时间。数据对齐
在我计算机上的各基本类型的所占字节数如下:有结构体A如下:
[code] 1: struct A
2: {
3: int i;
4: double d;
5: char c;
6: short s;
7: };
[/code]
数据对齐有两种方式,一种是自然对齐,另一种是强制对齐。
自然对齐
结构体数据自然对齐要满足的条件:1. 假设数据的偏移量X,数据所属类型所占字节数b,那么需要满足 X % b == 0。
2. 假设结构体中所占总字节数为N,结构体中占字节数最大的数据类型(比如结构体A中的double)的字节数为B。那么需要满足 N % B == 0。
现在分析结构体A
int i; int型占4个字节,结构体的第一个数据,所以偏移量为0(偏移量的单位是字节),能够整除4,满足条件一
double d; double 型占8个字节,偏移量为4,不能够整除8,不满足条件一,所以将其偏移量后移至8,从而满足条件一。
char c; char型占1个字节,偏移量为16,能够整除1,满足条件一。
short s; short型占2个字节,偏移量为17,不能够整除2,不满足条件一,所以将其偏移量后移至18,从而满足条件一。
综上所述: i的偏移量是0,d的偏移量是8,c的偏移量是16,s的偏移量是18。
假设struct A的起始地址为Addr,那么i,d,c,s的内存地址是Addr+各自的偏移量。
将所有字节加起来应该是20个字节,即struct A所占的内存空间应该是(结构体A的起始地址 ~ 结构体A的起始地址+19)。但是不满足条件2,在struct A中占字节数最大的数据类型是double占8个字节,所以总字节数为24。如何验证这一说呢?可以声明一个结构体数组A a[2];如果struct A真的占字节数为24,那么&a[1].i – &a[0].i的值应该等于24。换言之,short s占了两个字节之后还另占了4个字节的内存地址保持数据的对齐,&a[1].i – &a[0].i = 6。有图有真相:
从图中观察到两点
1.每个数据的内存地址都是struct A的起始地址(0x002afbac)+各自的偏移量。
2.&a[1].i - &a[0].s = 6从而验证了上面加粗字的内容为真。
强制对齐
强制对齐需要用到#pragma pack[code] 1: #pragma pack(1)
2:
3: struct B
4: {
5: int i;
6: double d;
7: char c;
8: short s;
9: };
10: #pragma pack()
[/code]
先不理会#pragma pack的具体功能,只需要知道它有一个参数即可。
结构体的强制对齐要满足:
1. 假设数据的偏移量X,数据所属类型所占字节数b1,#pragma pack(b2)的参数为b2,那么需满足 X % ( min ( b1, b2) ) == 0。
2. 假设结构体中所占总字节数为N,结构体中占字节数最大的数据类型(比如结构体A中的double)的字节数为B1,#pragma pack(b2)的参数为B2,那么应该满足
N % ( min( B1, B2) ) == 0。
#pragma pack( n ) 的作用就在条件1,2中体现了,也体现了强制对齐与自然对齐的区别。
现在分析结构体B(与结构体唯一的区别就是加了pack)所占的总字节数:
int i;偏移量为0,能够整除min (4, 1)。
double d;偏移量为4,能够整除min (8, 1)
char c;偏移量为12,能够整除min (1, 1)
short s;偏移量为13,能够整除min (2, 1)
所以最后的总字节数为15。又15能够整除min (8, 1),满足条件2,因此最后的总字节数为15。见真相:
总结
自然对齐其实是有默认的pack,在我的计算机中它的默认值为8(可通过#pragma pack(show)来查询默认值,运行的时候在警告栏中显示),也就是本文中的自然对齐与[code] 1: #pragma pack(8)
2:
3: struct A
4: {
5: int i;
6: double d;
7: char c;
8: short s;
9: };
10: #pragma pack()
[/code]
是等价的。
相关文章推荐
- 结构体的数据对齐
- 【C/C++】【VS开发】结构体存储空间数据对齐说明
- 初识联合体、结构体中的数据对齐问题
- 【LVL1_6_c】【思考】X86 c语言结构体数据对齐的规则
- 结构体中数据的内存对齐
- C结构体中数据的内存对齐问题【转自hbyh专栏】
- C结构体中数据的内存对齐问题
- 数据对齐 & 结构体的大小
- VC中结构体内存分配问题透析(“字节对齐”访问数据)
- 结构体数据对齐
- 腾讯笔试题—结构体的数据对齐
- C++学习之旅——结构体和联合体的区别,以及数据对齐方式影响内存大小
- c语言结构体数据对齐问题
- C语言结构体中的数据对齐
- 结构体字节对齐 windows下
- 字节对齐--结构体数据类型的存储
- 基本数据类型变量 结构体 union 类的内存字节对齐
- 结构体数据对齐
- NumPy-快速处理数据--ndarray对象--多维数组的存取、结构体数组存取、内存对齐、Numpy内存结构
- 结构体内存对齐以及基本数据类型夸平台大小