说说内存对齐吧

说说内存对齐

为什么要内存对齐?因为CPU为了提高指令提取效率,对数据的存放地址有要求。如果不对齐,会导致效率低下,
甚至错误。

如何对齐?既然CPU已经作了规范,剩下的事情就交给编译器了。对于程序员,可以告诉编译器按照怎么的方式去
对齐。不同的编译器指令不一样:
(1) windows的编译器cl

  #pragma pack(n) //n表示按多少字节对齐
  #pragma pack(show) //显示当前按多少字节对齐,编译时输出。比如:warning C4810: 杂注 pack(show) 的值 == 8表示按照8字节对齐
  #pragma pack() //表示按照默认字节对齐



(2) GCC

  __attribute((aligned (n))) //n表示按照多少字节对齐


 

下面在vs2010,x86平台下测试
一:例子1

//这里可以看到默认按8字节对齐
#pragma pack(show) //warning C4810: 杂注 pack(show) 的值 == 8
struct TestStruct1
{
 char a;
 char b;
 char c;
};//1字节对齐

struct TestStruct2
{
 char a;
 char b;
 int c;
};//4字节对齐。为什么呢?因为是取min{最大内存的数据成员大小,当前编译器对齐大小}

int main(int argc, char *argv[])
{

 std::cout<<sizeof(TestStruct1)<<std::endl;//输出结果:3
 std::cout<<sizeof(TestStruct2)<<std::endl;//输出结果:8
 return 0;
}


 

二:例子2,更改对齐方式为2字节对齐

#pragma pack(2) //warning C4810: 杂注 pack(show) 的值 == 8
#pragma pack(show) //warning C4810: 杂注 pack(show) 的值 == 2
struct TestStruct1
{
 char a;
 char b;
 char c;
};//1字节对齐

struct TestStruct2
{
 char a;
 char b;
 int c;
};//这里结构体最终按2字节对齐

int main(int argc, char *argv[])
{

 std::cout<<sizeof(TestStruct1)<<std::endl;//输出结果:3
 std::cout<<sizeof(TestStruct2)<<std::endl;//输出结果:6
 return 0;
}


 

三:例子3,结构体嵌套
这是一个很有意思的问题。首先看代码:

struct TestStruct1
{
 char a;
 char b;
 char c;
};//1字节对齐

struct TestStruct2
{
 char a;
 char b;
 int c;
};//这里结构体最终按4字节对齐

struct TestStruct3
{
 TestStruct1 t1;
 TestStruct2 t2;
};

int main(int argc, char *argv[])
{

 std::cout<<sizeof(TestStruct1)<<std::endl;//输出结果:3
 std::cout<<sizeof(TestStruct2)<<std::endl;//输出结果:8
 std::cout<<sizeof(TestStruct3)<<std::endl;//这个是多少?答案是12
 return 0;
}


 

TestStruct3的大小是多少?刚开始我以为是16,为什么呢,因为TestStruct2大小是8字节(注意,我说的是大小为8,而不是按8字节对齐),而编译器默认是按照8字节对齐,所以理论上
TestStruct3是按照8字节对齐的(取两者最小嘛,都是8). 但是结果确是12。为什么呢?因为TestStruct2虽然大小为8,但是仍然按4字节对齐,所以TestStruct3最终是按4字节对齐的。
结构体嵌套时,要注意对齐方式。下面是另外一个例子,在论坛找到的:http://bbs.csdn.net/topics/120048737 觉得有点意思,弄过来,命名上我改了一下。

struct TestStruct1
{
 char a;
 char b;
 char c;
 char d;
};//1字节对齐.大小为4
struct   TestStruct2     
{   
   char  a;       
   TestStruct1 b;
   char  c;     
};    
struct   TestStruct3     
{   
   char a;       
   int  b;
   char c;     
};

int main(int argc, char *argv[])
{

 std::cout<<sizeof(TestStruct1)<<std::endl;//输出结果:4
 std::cout<<sizeof(TestStruct2)<<std::endl;//输出结果:6
 std::cout<<sizeof(TestStruct3)<<std::endl;//输出结果:12
 return 0;
}


 

TestStruct1的大小和int是一样的,为什么会造成TestStruct3的大小不一样呢?原因在于TestStruct1按照1字节对齐,而int按照4字节对齐,所以
最终TestStruct2按照1字节对齐,而TestStruct3按照4字节对齐。

ok,内存对齐这玩意有点绕,但是需要特别注意。但有时候不能让数据按照默认的大小对齐,而必须自然排列,即按1字节对齐。这样就行了,很简单:
#pragma pack(push) //先保存之前的对齐方式
#pragma pack(n)    //设定对齐方式
struct Test {
 .....
};
#pragma pack(pop)  //恢复原来的对齐方式

或者:
#pragma pack(n)
struct Test {
 .....
};
#pragma pack() //按照默认的方式对齐

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值