`

VC结构字节对齐

    博客分类:
  • C++
 
阅读更多

 

1、 sizeof应用在结构上的情况

请看下面的结构:

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小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;

否则必须为n的倍数。下面举例说明其用法。

#pragma pack(push) //保存对齐状态

#pragma pack(4)//设定为4字节对齐

struct test

{

  char m1;

  double m4;

  int  m3;

};

#pragma pack(pop)//恢复对齐状态

以上结构的大小为16,下面分析其存储情况,首先为m1分配空间,其偏移量为0,满足我们自己设定的对齐方式(4字节对齐),m1占用1个字节。接着开始为m4分配空间,这时其偏移量为1,需要补足3个字节,这样使偏移量满足为n=4的倍数(因为sizeof(double)大于n),m4占用8个字节。接着为m3分配空间,这时其偏移量为12,满足为4的倍数,m3占用4个字节。这时已经为所有成员变量分配了空间,共分配了16个字节,满足为n的倍数。如果把上面的#pragma pack(4)改为#pragma pack(16),那么我们可以得到结构的大小为24。(请读者自己分析)

分享到:
评论

相关推荐

    C/C++结构体字节对齐详解

     我们先看看sizeof的定义——sizeof的结果等于对象或者类型所占的内存字节数,好吧,那让我们来看看S1的内存分配情况  S1 s1 = { 'a', 0xFFFFFFFF };  定义上面的变量后,加上断点,运行程序,观察s1所在的...

    浅析C++字节对齐容易被忽略的两个问题

    在这里就分享两条开发中曾经忽略的问题:1、Union(联合体)的字节对齐先...调试一下结构体的内存布局,发现,union自身增加了2个字节的填充,用来保持Union本身的4字节对齐。即union在内存中变成:union{double dTest

    内存对齐问题的完美解释.doc

    在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。下面列出常用类型的对齐方式(vc6.0,32位系统)。 类型 对齐方式(变量存放的起始地址相对于...

    c++ 面试题 总结

    块式管理:把主存分为一大块、一大块的,当所需的程序片断不在主存时就分配一块主存空间,把程 序片断load入主存,就算所需的程序片度只有几个字节也只能把这一块分配给它。这样会造成很大的浪费,平均浪费了50%的...

    吕鑫:最博大精深的C语言视频教程 第22天 【第3堂课】位域结构体与联合体

    1、讲解位域结构体的原理和使用方法以及字节对齐问题; 2、讲解联合的概念以及联合体成员变量的内存分布;

    MASM最新可用编译\连接器

    压缩包里包括的文件: RcDll.Dll 版本 6.1.7600.1635 cvtres.exe 版本 10.0.30319.1 ...需要说明的是,用这link出来的东西比MASM32 10自带link的稍大一点, 可能是字节对齐问题吧(比如原来的体积是8.5K,用这新的变成9.0K)

    Visual C++开发经验技巧宝典(第1章)

    0031 结构体的字节对齐 11 1.3 模板与函数 12 0032 成员函数的模板不可以是虚函数 12 0033 利用递归函数计算阶乘 12 0034 函数模板的应用 13 0035 使用指针数组 13 0036 函数指针数组的应用 13 0037 ...

    PT80-NEAT开发指南v1.1

    NEAT 开 发 指南 文档 适用于 PT80 系列 移动数据终端 版本记录 版本号 版本描述 发布日期 V 1.0 初始版本。 2012-04-12 V1.1 修改前三章内容 2012-09-25 目录 第一章 关于本手册.....................................

    C语言程序设计标准教程

    结构类型 ?联合类型 3.指针类型  指针是一种特殊的,同时又是具有重要作用的数据类型。其值用来表示某个量在内存储器中的地址。虽然指针变量的取值类似于整型量,但这是两个类型完全不同的量,因此不能混为一谈。...

    C++MFC教程

    +-- 第一章 VC入门 |------ 1.1 如何学好VC |------ 1.2 理解Windows消息机制 |------ 1.3 利用Visual C++/MFC开发Windows程序的优势 |------ 1.4 利用MFC进行开发的通用方法介绍 |------ 1.5 MFC中常用类,宏,函数...

    易语言程序免安装版下载

     静态编译后的易语言可执行程序(exe)和动态链接库(dll),运行时不再依赖任何支持库文件,文件尺寸更小(相对以前的独立编译),PE结构更合理(取消了“易格式体”),加载速度更快,而且有效解决了“病毒误报”和...

Global site tag (gtag.js) - Google Analytics