首页 > 代码库 > 字节对齐问题详解
字节对齐问题详解
字节对齐,我的理解就是用空间换取时间,提高存取的效率。下面详细分析:
1.什么是字节对齐?
现代计算机中内存空间都是按照字节划分的,从理论上讲似乎对任何类型变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是字节对齐。
注意:我们经常听说的对齐在N上,它的含义就是数据的存放起始地址%N==0。
2.原因及其意义:
各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐。其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对 数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那 么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据。
struct Test
{
char ch;
int in;
}test;
假设变量test存放在内存中的起始地址为0x00,那么其成员变量ch的起始地址为0x00,成员变量i的起始地址0x01,变量test一共占用了5个字节。当CPU要对成员变量ch进行访问时,只需要一个读周期即可。而如若要对成员变量in进行访问,那么情况就变得有点复杂了,首先CPU用了一个读周期,从0x00处读取了4个字节(注意由于是32位架构),然后将0x01-0x03的3个字节暂存,接着又花费了一个读周期读取了从0x04-0x07的4字节数据,将0x04这个字节与刚刚暂存的3个字节进行拼接从而读取到成员变量in的值。为了读取这个成员变量in,CPU花费了整整2个读周期。试想一下,如果数据成员i的起始地址被放在了0x04处,那么读取其所花费的周期就变成了1,显然引入字节对齐可以避免读取效率的下降,但这同时也浪费了3个字节的空间(0x01-0x03),即用空间换取了时间。
下面我们讲三个重要概念:自身对齐值,指定对齐值和有效对齐值。
①自身对齐值:即数据类型的自身的对齐值。例如char型的数据,其自身对齐值为1字节;short型的数据,其自身对齐值为2字节;int,float,long类型,其自身对齐值为4字节;double类型,其自身对齐值为8字节;而struct和class类型的数据其自身对齐值为其成员变量中自身对齐值最大的那个值。
②指定对齐值:#pragma pack (value)时指定的对齐值value。
③有效对齐值:min(自身对齐值,指定对齐值)。
3.准则:
#include <stdio.h>
#include <iostream>
using namespace std;
struct A {
char c;
int i;
short s;
};
struct B {
char c;
short s;
int i;
};
void main()
{
cout << sizeof(struct A) << " " << sizeof(struct B) << endl
对于联合体union:
#include <iostream>
#include <stdio.h>
using std::cout;
using std::endl;
union u1
{
double a;
int b;
};
union u2
{
char a[13];
int b;
};
union u3
{
char a[13];
char b;
};
#pragma pack(2)//对界方式2字节¨2
union u4
{
char a[13];
int b;
};
union u5
{
char a[13];
char b;
};
#pragma pack() //恢复默认对界方式
void main()
{
cout<<sizeof(u1)<<endl;
cout<<sizeof(u2)<<endl;
cout<<sizeof(u3)<<endl;
cout<<sizeof(u4)<<endl;
cout<<sizeof(u5)<<endl;
system("pause");
}
测试结果如下:
8
16
13
14
13
Union就是取整个成员中大的内存块作为整个共用体的内存大小。
结论:由于默认是4字节(32位系统)对齐, 在u1 中a为8字节,很明显u1的大小就为8。在u2中由于int为4字节,char为1 个字节,所以min(4,max(4,1))=4,以4字节对齐,u2理论为13个字节,要以4字节对齐的话所以为16字节。同理 u3 :min(max(1,1),4)=1,sizeof(u3)=13,
u4:min(max(1,4),2)=2,sizeof(u4)=14,
u5:min(max(1,1),2)=1,sizeof(u5)=13。
字节对齐问题详解