1.对齐的原因
对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。其他平台可能没有这种情况, 但是最常见的是如果不按照适合其平台的要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为 32位)如果存放在偶地址开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,并对两次读出的结果的高低 字节进行拼凑才能得到该int数据。显然在读取效率上下降很多。这也是空间和时间的博弈。
2.对齐的实现
编译器对数据存放做了对齐,平常我们在写程序的时候都不需要考虑这个问题,但在我们用sizeof求struct结构体的大小的时候,产生的结果往往出乎意料。
现在定义结构体如下:
struct A
{
int a;
char b;
short c;
};
{
int a;
char b;
short c;
};
结构体A里面定义了一个4字节的int变量,一个1字节的char变量,一个2字节的short变量。
我的编译器上面是默认的4字节对齐,所以sizeof(struct A)是 8.
现在又定义如下结构体B
sizeof(struct C) 是 8。#pragma pack (2) 指定编译器2字节对齐,#pragma pack() 还原默认的对齐方式。因为b是4字节的,其占的字节数不会变,然后a和c各占2字节,所以总共是8字节。
struct B
{
char a;
int b;
short c;
};
{
char a;
int b;
short c;
};
结构体B里面定义了一个1字节的char变量,一个4字节的int变量,一个2字节的short变量。
但这次sizeof(struct B)是 12
结构体A和结构体B总共的所用的字节大小都是7字节,但两者sizeof运算的结果却不一样,这就是字节对齐的方式有关了。
首先我的gcc编译器默认是4字节对齐的。
结构体A首先是定义了一个4字节的int变量,与默认对齐一样,然后定义了一个1字节的char变量,最后是一个2字节的
short变量,由于第二个char变量只占了1字节,而对齐方式是4字节,所以就空一字节,把最后定义的2字节的变量拿
上来补齐。大致的内存如下:
所以只有sizeof(struct A) 是 8;
结构体B首先定义了一个1字节的char变量,然后定义了一个4字节的int变量,最后是一个2字节的short变量。
由于中间的是一个4字节的int变量,所以不存在补齐,大致的内存的如下:
然后在这里在说一下
预编译指令#pragma pack (value)的用法。这个预编译指令主要改变编译器默认的字节对齐方式,变成指定的value值。
#pragma pack (2)
struct C
{
short a;
int b;
char c;
};
#pragma pack ()
struct C
{
short a;
int b;
char c;
};
#pragma pack ()
转载于:https://blog.51cto.com/lutianba/1192571