结构体中数据的对齐性

原创 2006年06月09日 18:12:00

对齐

        对齐性是一内存地址的特性,表现为内存地址模上 2 。例如,内存地址 0x0001103F 4 3 个地址就叫做与 4n 3 对齐 4 指出了所用的 2 。内存地址的对齐性取决于所选择 2 幂值。同的地址模 8 7

 

       一个内存地址符合表达式 Xn 0 ,那说该地址对齐 X

 

       CPU 行指令就是于内存上的数据行操作,些数据在内存上是以地址为标记的。于地址来独的数据会有其占用内存的字数。如果它的地址对齐于它的字数,那就称作数据自然对齐,否对齐。例如,一个标记 8 的浮点数据的地址对齐 8 ,那么这数据就自然对齐

 

数据对齐性的编译处

       设备编译器以一防止造成数据未对齐的方式来数据行地址分配。

 

       个的数据型,编译其分配的地址是数据型字数的倍数。因此,编译器分配 long 量的地址 4 的倍数,就是 2 制表示地址的,最后两位 0

 

       另外,编译器以一自然对齐每构成的方式来填充构体。参看下面的代里面的构体 struct x_

 

     struct x_

      {

            char a;     // 1 byte

            int b;      // 4 bytes

            short c;    // 2 bytes

            char d;     // 1 byte

      } MyStruct;

 

      编译器填充构以使其自然对齐

 

例如

      下面的代码说明了编译器是如何在内存中填充的。

 

      // Shows the actual memory layout

      struct x_

     {

           char a;            // 1 byte

           char _pad0[3];     // padding to put 'b' on 4-byte boundary

           int b;            // 4 bytes

           short c;          // 2 bytes

           char d;           // 1 byte

           char _pad1[1];    // padding to make sizeof(x_) multiple of 4

     }

 

     在作sizeof(struct x_)运算都会返回12

 

      第二含有两填充成分:

 

             *char _pad0[3]使得int b 4节边界上对齐

 

             *char _pad1[1]使得构数struct _x  bar[3]对齐

             填充使得bar[3]各个量能自然对齐

 

看下面的构:

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分配空,其起始地址跟构的起始地址相同(好偏移量0sizeof(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分配空这时其偏移量124的倍数,m3占用4个字这时经为所有成员变量分配了空,共分配了16个字n的倍数。如果把上面的#pragma pack(4)#pragma pack(16),那可以得到构的大小24。(请读者自己分析)

对结构体中的数据进行排序

#include #include const int S=51000; using namespace std; struct TT { int id,v1,v2; }f[S]; boo...
  • yanxiuhao
  • yanxiuhao
  • 2013年08月10日 15:54
  • 1258

结构体中用字符串排序的sort自定义函数和 结构体的操作

此函数为快速排序中自定义函数的写法,这是对结构体中的字符串来排序:sort(&str2[0],&str2[0]+t,cmp);bool cmp(const Person a,const Person ...
  • qq_31828929
  • qq_31828929
  • 2016年11月28日 22:52
  • 403

qsort对数组字符串/结构体字符串排序

百度找了好久都不能 最后问的学姐 解决啦 谢谢任真学姐啦 #include #include #include int cmp(const void *a,const void *b) { ...
  • su20145104009
  • su20145104009
  • 2015年04月01日 17:58
  • 1826

快排调用及结构体排序

快排的两种调用: #include #include #include #include #include using namespace std; int a[10000]; bool cmp...
  • nucyangjiayun
  • nucyangjiayun
  • 2016年07月14日 16:54
  • 1284

结构体数组中的某个成员进行排序

class Program    {        static void Main(string[] args)        {                                  ...
  • meifage2
  • meifage2
  • 2011年07月17日 21:59
  • 1894

C++对类或结构体进行指定规则排序

STL中就自带了排序函数sortsort 对给定区间所有元素进行排序.使用#include sort即可使用,语法描述为:sort(begin,end,cmp),表示一个范围。其中cmp是自己指定的...
  • xyisv
  • xyisv
  • 2017年12月03日 17:51
  • 92

从文件中读取结构体变量的数据读取和写入结构体数据到文件

#include size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); size_t fwrite(co...
  • u010261063
  • u010261063
  • 2016年09月23日 17:26
  • 542

C语言-对一个结构体中的字段进行排序

这是帮别人做的一个题目,好久没有接触过C语言了,有点发怵,不过似乎找回点当时学C语言,做课程设计的感觉。 题目:定义一个数组(学生结构体数组),里面包含学号、姓名、身份证和三科学生成绩,要求写一个函...
  • u013147600
  • u013147600
  • 2015年07月12日 12:39
  • 2678

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

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

c语言结构体中数据的存放机制

#include typedef struct DA da; struct DA {     da* next;     int a;     int b[2];     int *c;...
  • izzxacbbt
  • izzxacbbt
  • 2017年12月26日 17:17
  • 31
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:结构体中数据的对齐性
举报原因:
原因补充:

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