数据的字节对齐(data structure alignment)
2011-06-20 23:10
344 查看
1.1.1 为什么需要字节对齐
1、处理器的差异
有的处理器,不容许在字节未对齐的地址上访问字或者是多个字的数据。比如sun sparc cpu,不容许在奇数字节上访问一个字,否则会出现异常。
2、出于CPU读取内存数据效率的考虑。
CPU访问内存的时候,都是以字为单位的,如果要读取的数据不在字节对齐的位置上,就要对一次读取数据的操作。比如,在下面的内存模式中,如果要读取0x0000C004处一个字的数据,那么只需要读取一次。如果要读取0x0000C009处一个字的数据,那么需要两次读取,0x0000C009~0x0000C00B一次,0x0000C00C一次。
C语言中,基本数据类型默认的对齐方式:
结构对齐的基本原则:
1、结构体对齐的字节数是此结构体所有成员对齐的字节数中的最大值。
2、结构体每一个成员自身要保持字节对齐。
3、如果结构体中包含嵌套子结构体,那么子结构体自身必须对齐。
4、对于整个结构体,要根据规则1中“结构体对齐的字节数”满足字节对齐,对于没有对齐的情况,需要在最后增加pading。
举例说明:
示例一:
//因为成员d1是double类型,8字节对齐,并且是所有成员中最大的,所以align_sub_test_1也是8字节对齐,根据原则1
struct align_sub_test_1
{
double d1;
char c1;
char pading[7];//为了保证此结构体字节对齐,所以需要填充7个空位,根据原则4
};
//因为成员sub0是8字节对齐,并且是所有成员中最大的,所以align_test_1也是8字节对齐,根据原则1
struct align_test_1
{
struct align_sub_test_1 sub0;
char c;
char array[2];
char pading[1];//为了保证成员i能够字节对齐,所以需要填充1个空位,根据原则2
short i;
char pading[2];//为了保证整个结构体8字节对齐,所以需要填充2个空位,根据原则4
};
测试如下:
size_t l = sizeof(struct align_test_1);//l的值是
struct align_test_1 a1;
a1.sub0.d1 = 1;
a1.sub0.c1 = 3;
a1.i = 7;
a1.c = 5;
a1在内存中的表示为:
00 00 00 00 00 00 f0 3f 03 cc cc cc cc cc cc cc 05 cc cc cc 07 00 cc cc
示例二:
//因为成员i是short类型,2字节对齐,并且是所有成员中最大的,所以align_sub_test_2也是2字节对齐,根据原则1
struct align_sub_test_2
{
short i;
char array[2];
char c;
char pading[1];//为了保证此结构体字节对齐,所以需要填充1个空位,根据原则4
};
//因为成员d1是double类型,8字节对齐,并且是所有成员中最大的,所以align_test_2也是8字节对齐,根据原则1
struct align_test_2
{
struct align_sub_test_2 sub1;
short s1;
short s2;
char pading[6];//为了保证成员d1能够8字节对齐,所以需要填充6个空位,根据原则2
double d1;
};
测试如下:
size_t l2 = sizeof(struct align_test_2);//l2的值是24
struct align_test_2 a2;
a2.sub1.i = 1;
a2.sub1.c = 3;
a2.s1 = 5;
a2.s2 = 7;
a2.d1 = 9;
a2在内存中的表示为:
01 00 cc cc 03 cc 05 00 07 00 cc cc cc cc cc cc 00 00 00 00 00 00 22 40
示例三:
//因为成员i是int类型,4字节对齐,并且是所有成员中最大的,所以align_sub_test_3也是4字节对齐,根据原则1
struct align_sub_test_3
{
int i;
char c;
char pading[3];//为了保证此结构体字节对齐,所以需要填充3个空位,根据原则4
};
//因为成员sub2是align_sub_test_3类型,8字节对齐,并且是所有成员中最大的,所以align_test_3也是8字节对齐,根据原则1
struct align_test_3
{
struct align_sub_test_3 sub2;
char c1;
char pading[1];//为了保证成员s1能够2字节对齐,所以需要填充1个空位,根据原则2
short s1;
char c2;
char pading[3];//为了保证此结构体8字节对齐,所以需要填充3个空位,根据原则4
};
测试如下:
size_t l3 = sizeof(struct align_test_3);//l3的值是16
struct align_test_3 a3;
a3.sub2.i = 1;
a3.sub2.c = 3;
a3.c1 = 5;
a3.s1 = 7;
a3.c2 = 9;
a3在内存中的表示为:
01 00 00 00 03 cc cc cc 05 cc 07 00 09 cc cc cc
参考:http://en.wikipedia.org/wiki/Data_structure_alignment
1、处理器的差异
有的处理器,不容许在字节未对齐的地址上访问字或者是多个字的数据。比如sun sparc cpu,不容许在奇数字节上访问一个字,否则会出现异常。
2、出于CPU读取内存数据效率的考虑。
CPU访问内存的时候,都是以字为单位的,如果要读取的数据不在字节对齐的位置上,就要对一次读取数据的操作。比如,在下面的内存模式中,如果要读取0x0000C004处一个字的数据,那么只需要读取一次。如果要读取0x0000C009处一个字的数据,那么需要两次读取,0x0000C009~0x0000C00B一次,0x0000C00C一次。
Address | Byte0 | Byte1 | Byte2 | Byte3 |
0x0000C000 | ||||
0x0000C004 | 01 | 02 | 03 | 04 |
0x0000C008 | 11 | 22 | 33 | |
0x0000C00C | 44 | |||
0x0000C010 |
1.1.1 数据字节对齐讨论
我们在32位x86机器上,以c语言的struct结构为例,讨论字节对齐问题。C语言中,基本数据类型默认的对齐方式:
类型 | 长度(字节) | 对齐方式 |
Char | 1 | 1字节对齐 |
short | 2 | 2字节对齐 |
int | 4 | 4字节对齐 |
long | 4 | 4字节对齐 |
Float | 4 | 4字节对齐 |
double | 8 | 8字节对齐(windows);4字节对齐(linux) |
指针 | 4 | 4字节对齐 |
1、结构体对齐的字节数是此结构体所有成员对齐的字节数中的最大值。
2、结构体每一个成员自身要保持字节对齐。
3、如果结构体中包含嵌套子结构体,那么子结构体自身必须对齐。
4、对于整个结构体,要根据规则1中“结构体对齐的字节数”满足字节对齐,对于没有对齐的情况,需要在最后增加pading。
举例说明:
示例一:
//因为成员d1是double类型,8字节对齐,并且是所有成员中最大的,所以align_sub_test_1也是8字节对齐,根据原则1
struct align_sub_test_1
{
double d1;
char c1;
char pading[7];//为了保证此结构体字节对齐,所以需要填充7个空位,根据原则4
};
//因为成员sub0是8字节对齐,并且是所有成员中最大的,所以align_test_1也是8字节对齐,根据原则1
struct align_test_1
{
struct align_sub_test_1 sub0;
char c;
char array[2];
char pading[1];//为了保证成员i能够字节对齐,所以需要填充1个空位,根据原则2
short i;
char pading[2];//为了保证整个结构体8字节对齐,所以需要填充2个空位,根据原则4
};
测试如下:
size_t l = sizeof(struct align_test_1);//l的值是
struct align_test_1 a1;
a1.sub0.d1 = 1;
a1.sub0.c1 = 3;
a1.i = 7;
a1.c = 5;
a1在内存中的表示为:
00 00 00 00 00 00 f0 3f 03 cc cc cc cc cc cc cc 05 cc cc cc 07 00 cc cc
示例二:
//因为成员i是short类型,2字节对齐,并且是所有成员中最大的,所以align_sub_test_2也是2字节对齐,根据原则1
struct align_sub_test_2
{
short i;
char array[2];
char c;
char pading[1];//为了保证此结构体字节对齐,所以需要填充1个空位,根据原则4
};
//因为成员d1是double类型,8字节对齐,并且是所有成员中最大的,所以align_test_2也是8字节对齐,根据原则1
struct align_test_2
{
struct align_sub_test_2 sub1;
short s1;
short s2;
char pading[6];//为了保证成员d1能够8字节对齐,所以需要填充6个空位,根据原则2
double d1;
};
测试如下:
size_t l2 = sizeof(struct align_test_2);//l2的值是24
struct align_test_2 a2;
a2.sub1.i = 1;
a2.sub1.c = 3;
a2.s1 = 5;
a2.s2 = 7;
a2.d1 = 9;
a2在内存中的表示为:
01 00 cc cc 03 cc 05 00 07 00 cc cc cc cc cc cc 00 00 00 00 00 00 22 40
示例三:
//因为成员i是int类型,4字节对齐,并且是所有成员中最大的,所以align_sub_test_3也是4字节对齐,根据原则1
struct align_sub_test_3
{
int i;
char c;
char pading[3];//为了保证此结构体字节对齐,所以需要填充3个空位,根据原则4
};
//因为成员sub2是align_sub_test_3类型,8字节对齐,并且是所有成员中最大的,所以align_test_3也是8字节对齐,根据原则1
struct align_test_3
{
struct align_sub_test_3 sub2;
char c1;
char pading[1];//为了保证成员s1能够2字节对齐,所以需要填充1个空位,根据原则2
short s1;
char c2;
char pading[3];//为了保证此结构体8字节对齐,所以需要填充3个空位,根据原则4
};
测试如下:
size_t l3 = sizeof(struct align_test_3);//l3的值是16
struct align_test_3 a3;
a3.sub2.i = 1;
a3.sub2.c = 3;
a3.c1 = 5;
a3.s1 = 7;
a3.c2 = 9;
a3在内存中的表示为:
01 00 00 00 03 cc cc cc 05 cc 07 00 09 cc cc cc
参考:http://en.wikipedia.org/wiki/Data_structure_alignment
相关文章推荐
- 数据对齐---C语言:内存字节对齐详解
- 数据的对齐(alignment)
- 面试的时候经常遇到数据类型字节大小,字节对齐的问题,现整理如下
- OpenCV图像数据字节对齐问题
- HBITMAP对位图数据存储的字节对齐
- 数据对齐---C语言:内存字节对齐详解
- 字节对齐陷阱(Alignment trap)-demo for ARM9
- C#中struct的字节对齐、转换操作和复制为二进制数据(byte[])
- C语言字节对齐 数据对齐详解
- 关于IMAGE_OPTIONAL_HEADER.SectionAlignment与IMAGE_OPTIONAL_HEADER.FileAlignment 以及内存映射的字节对齐
- 嵌入式linux 字节对齐 导致输出Alignment trap
- 数据对齐(alignment & endian)
- 字节对齐--结构体数据类型的存储
- 基本数据类型变量 结构体 union 类的内存字节对齐
- 数据对齐 字节对齐
- MFC显示Mat数据格式(Opencv)图片,保证4字节对齐,图片缩放不错行
- Linux kernel data types, alignment, compat_ioctl 数据类型,对齐问题和compat_ioctl
- 数据结构基础之memset---有memset 抛出的int 和 char 之间的转换和字节对齐
- 定义网络数据报文--字节对齐
- chrome 中在栈上创建指定字节对齐的POD类型的static数据的一种可移植的方法