关于字节对齐的问题(vs.net)(转载)

转载 2007年10月14日 13:55:00

转自http://nephen.bokee.com/4739983.html

关于字节对齐的问题(vs.net)

                                      

请看下面的结构:

struct MyStruct
{
double dda1;
char dda;
int type
};

  对结构MyStruct采用sizeof会出现什么结果呢?sizeof(MyStruct)为多少呢?也许你会这样求:

                 sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13

  但是当在VC中测试上面结构的大小时,你会发现sizeof(MyStruct)为16。你知道为什么在VC中会得出这样一个结果吗?

  其实,这是VC对变量存储的一个特殊处理。为了提高CPU的存储速度,VC对一些变量的起始地址做了“对齐”处理。在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。下面列出常用类型的对齐方式(vc6.0,32位系统)。

  类型
  对齐方式(变量存放的起始地址相对于结构的起始地址的偏移量)

  Char
  偏移量必须为sizeof(char)即1的倍数

  int
  偏移量必须为sizeof(int)即4的倍数

  float
  偏移量必须为sizeof(float)即4的倍数

  double
  偏移量必须为sizeof(double)即8的倍数

  Short
  偏移量必须为sizeof(short)即2的倍数

  各成员变量在存放的时候根据在结构中出现的顺序依次申请空间,同时按照上面的对齐方式调整位置,空缺的字节VC会自动填充。同时VC为了确保结构的大小为结构的字节边界数(即该结构中占用最大空间的类型所占用的字节数)的倍数,所以在为最后一个成员变量申请空间后,还会根据需要自动填充空缺的字节。

  下面用前面的例子来说明VC到底怎么样来存放结构的。

struct MyStruct
{
double dda1;
char dda;
int type
};

  为上面的结构分配空间的时候,VC根据成员变量出现的顺序和对齐方式,先为第一个成员dda1分配空间,其起始地址跟结构的起始地址相同(刚好偏移量0刚好为sizeof(double)的倍数),该成员变量占用sizeof(double)=8个字节;接下来为第二个成员dda分配空间,这时下一个可以分配的地址对于结构的起始地址的偏移量为8,是sizeof(char)的倍数,所以把dda存放在偏移量为8的地方满足对齐方式,该成员变量占用sizeof(char)=1个字节;接下来为第三个成员type分配空间,这时下一个可以分配的地址对于结构的起始地址的偏移量为9,不是sizeof(int)=4的倍数,为了满足对齐方式对偏移量的约束问题,VC自动填充3个字节(这三个字节没有放什么东西),这时下一个可以分配的地址对于结构的起始地址的偏移量为12,刚好是sizeof(int)=4的倍数,所以把type存放在偏移量为12的地方,该成员变量占用sizeof(int)=4个字节;这时整个结构的成员变量已经都分配了空间,总的占用的空间大小为:8+1+3+4=16,刚好为结构的字节边界数(即结构中占用最大空间的类型所占用的字节数sizeof(double)=8)的倍数,所以没有空缺的字节需要填充。所以整个结构的大小为:sizeof(MyStruct)=8+1+3+4=16,其中有3个字节是VC自动填充的,没有放任何有意义的东西。

  下面再举个例子,交换一下上面的MyStruct的成员变量的位置,使它变成下面的情况:

struct MyStruct
{
char dda;
double dda1;
int type
};

  这个结构占用的空间为多大呢?在VC6.0环境下,可以得到sizeof(MyStruc)为24。结合上面提到的分配空间的一些原则,分析下VC怎么样为上面的结构分配空间的。(简单说明)

struct MyStruct
{
char dda;//偏移量为0,满足对齐方式,dda占用1个字节;
double dda1;//下一个可用的地址的偏移量为1,不是sizeof(double)=8
//的倍数,需要补足7个字节才能使偏移量变为8(满足对齐
//方式),因此VC自动填充7个字节,dda1存放在偏移量为8
//的地址上,它占用8个字节。
int type;//下一个可用的地址的偏移量为16,是sizeof(int)=4的倍
//数,满足int的对齐方式,所以不需要VC自动填充,type存
//放在偏移量为16的地址上,它占用4个字节。
};//所有成员变量都分配了空间,空间总的大小为1+7+8+4=20,不是结构
//的节边界数(即结构中占用最大空间的类型所占用的字节数sizeof
//(double)=8)的倍数,所以需要填充4个字节,以满足结构的大小为
//sizeof(double)=8的倍数。

  所以该结构总的大小为:sizeof(MyStruc)为1+7+8+4+4=24。其中总的有7+4=11个字节是VC自动填充的,没有放任何有意义的东西。

  VC对结构的存储的特殊处理确实提高CPU存储变量的速度,但是有时候也带来了一些麻烦,我们也屏蔽掉变量默认的对齐方式,自己可以设定变量的对齐方式。

  VC中提供了#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说如果成员变量所需要的空间大于n,则偏移量只需要为n的整数倍数即可(默认为所需空间的倍数);否则按默认处理。

下面举例说明其用法。

#pragma pack(push) //保存对齐状态
#pragma pack(4)//设定为4字节对齐
struct test
{
char m1;
double m4;
int m3;
};
#pragma pack(pop)//恢复对齐状态

  以上结构的大小为16,下面分析其存储情况,首先为m1分配空间,char型,占1字节,1小于4,按默认处理,其偏移量为0,满足1的倍数,m1占用1个字节。接着开始为m4分配空间,double型,占8个字节,8大于4,但这里只需按4的整数倍数对齐即可。这时其偏移量为1,只需要补足3个字节,m4占用8个字节。接着为m3分配空间,int型,占4个字节,按默认处理,这时其偏移量为12,满足为4的倍数,m3占用4个字节。这时已经为所有成员变量分配了空间,共分配了16个字节。本结构中占用空间最大的是double型,8个字节,8比4大,但这里只需按4的整数倍数对齐。已经满足4的整数倍数,故不用再填充字节。

如果把上面的#pragma pack(4)改为#pragma pack(16),那么我们可以得到结构的大小为24。(请读者自己分析)

  注:C/C++中的sizeof操作符得到的值是经过这些调整后的字节数。

 

32位和64位系统区别及字节对齐

(一)64位系统和32位区别? (二)数据类型对应的字节数 (三)字节对齐
  • lz20120808
  • lz20120808
  • 2015年11月18日 19:28
  • 1507

C++中对字节对齐的理解

前几天时,在公司和同事说到了字节对齐,一直对这个概念比较模糊,只是在《程序员面试宝典》中看到过简单的描述和一些面试题。后来在论坛中有看到有朋友在询问字节对齐的相关问题,自己也答不上来,觉得应该研究一下...
  • weiyuxinyuan
  • weiyuxinyuan
  • 2016年12月11日 14:54
  • 877

细说C++中字节的对齐方式

C++中字节的对齐方式可以采用编译器默认的字节对齐方式, 也可以采用自定义的对齐方式。 编译器默认字节对齐方式 1、结构体中每个成员分别按自己的方式对齐(注:对于数组如int a[3], 其对齐字...
  • yanhang1589
  • yanhang1589
  • 2015年05月26日 16:39
  • 1647

C语言字节对齐、结构体对齐最详细的解释

文章最后本人做了一幅图,一看就明白了,这个问题网上讲的不少,但是都没有把问题说透。   一、概念       对齐跟数据在内存中的位置有关。如果一个变量的内存地址正好位于它长度的整数倍,他就...
  • lanzhihui_10086
  • lanzhihui_10086
  • 2015年03月17日 21:57
  • 9494

struct 字节对齐详解

一.什么是字节对齐,为什么要对齐?     现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的...
  • fivedoumi
  • fivedoumi
  • 2015年11月18日 11:42
  • 928

pragma pack(非常有用的字节对齐用法说明)

声明: 整理自网络达人们的帖子,部分参照MSDN。 强调一点: #pragma pack(4) typedef struct {     char bu...
  • hellokandy
  • hellokandy
  • 2016年12月23日 09:50
  • 955

什么是字节对齐,为什么要对齐

一.什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任 何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内...
  • etwdone
  • etwdone
  • 2013年03月22日 09:48
  • 880

MFC显示Mat数据格式(Opencv)图片,保证4字节对齐,图片缩放不错行

/*! 在MFC的Picture Control控件中显示Mat数据 *! Mat img: 需要显示的Mat数据 *! UINT nID: 控件的ID号 *! 支持直接传入 BGR ,B...
  • huixingshao
  • huixingshao
  • 2017年05月11日 11:41
  • 366

为什么需要字节对齐

概念   在C语言中,结构是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如数组、结构、联合等)的数据单元。在结构中,编译器为...
  • qq_25077833
  • qq_25077833
  • 2016年12月04日 16:37
  • 521

字节不对齐,后果很严重

最近公司的软件需要从windows版本移植到solaris版本(我们用的V240机器,sparc芯片,solaris9),移植倒是很顺利,虽然vc对C++标准的支持不是很严格,到了GCC以后,很多地方...
  • sepnineth
  • sepnineth
  • 2014年03月03日 14:48
  • 1890
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于字节对齐的问题(vs.net)(转载)
举报原因:
原因补充:

(最多只允许输入30个字)