C语言的字节对齐

来源:互联网 发布:祺嫔 知乎 编辑:程序博客网 时间:2024/04/30 14:58

一、WINDOWS下(VC--其实GCC和其原理基本一样,象这种问题,一般要查具体的编译器设置)字节对齐的规则:

1、一般设置的对齐方式为1,2,4字节对齐方式,VC一般默认为4字节(最大为8字节)。结构的首地址必须是结构内最宽类型的整数倍地址;另外,结构体的每一个成员起始地址必须是自身类型大小的整数倍(需要特别注意的是windows下是这样的,但在linux的gcc编译器下最高为4字节对齐),否则在前一类型后补0;这里特别提到的是数组一定要注意,而且在一些编程的技巧中,我们可以使用数组强制字节达到对齐的目的。这在网络编程中是很常见的。

举例:比如CHAR型占用空间为1字节,则其起始位置必须可被1整除。INT为4字节,其起始位置必须被4带队,依次类推。(我们假定类或结构体的起始位置为0位置,其实编译器是在开辟空间时,会寻找起始位置可被结构内最宽类型整除的地址做为开始地址,因此我们可以假定其为0值,因为这0值可以被任意的类型整除。)

2、结构体的整体大小必须可被对齐值整除,默认4(默认,且结构中的类型大小都小于默认的4)。

3、结构体的整体大小必须可被本结构内的最宽类型整除。(其实和上一条是一样的,但这里独立出来,起注意作用。比如结构体里的有DOUBLE,那么结构的大小最后必须可被8整除)

注意:GCC不是这样,就是最高只能被4整除,它是个死的。

否则(2、3条),编译器会在结构的最后添充一定的特定字符来补齐。

struct T
{
  char ch;
  double   d   ;
};

在VC中是16个字节,GCC中为12个字节。

4、对于结构体内嵌套结构体的形势,规定是必须按照基本数据类型来定义,而不能以嵌套结构大小来做为上三种使用的基准。

二、举例:

struct A
{
    int a;
    char b;
    short c;
};
struct B
{
    char b;
    int a;
    short c;
};
struct C
{
 double t;
    char b;
    int a;
    short c;
};
struct D
{
 char b;
 double t;
    int a;
    short c;
};

在VC中,SIZEOF这四个结构体,分别为:8、12、24、24;

我们先谈第一个,(说明一下,在考虑结构体大小时,我们基本可以忽略起始地址的问题,因为这个编译器会自动为我们做好,见上面的说明),结构体内首先是一个INT的4字节,起始地址假定为0,整除4,其小于等于默认的4字节对齐且0为4(INT的占用空间)的整数倍,所以,其占四个字节;其后为起始地址为5,空间为1个字节的CHAR,小于4且5为1(CHAR占用空间)的整数倍,故占用1个字节,然后是一个起始地址为5占2个字节的SHORT,其小于4,但5不为2位数,故补齐一个字节,从第6个字节开始,占2字节空间。所以共占用4+1+1(补)+2=8;8/4=2;整除,故占用8字节空间。

再谈第2个,CHAR不用解释,占有一个字节空间,且可以被0地址整除。而INT则占4字节空间,所以其必须在CHAR后补齐3字节,到第四个字节,才是INT的真正地址。SHORT也不用说,所以共占有:1+3(补)+4+2=10个字节,但10不能整除4,所以要在结构体最后补齐2字节。故实际占有10+2= 12个字节。

谈第三个,C结构体只是在B结构体前加了一个DOUBLE,其它都一样,按说应该是20个字节啊,但注意我们上面规则的第3条。必须是最宽类型的整数倍,一定要分清,所以得补齐到24,D结构体类似,不再讲。

三,字节对齐的控制

主要是使用:

#pragma pack (2) /*指定按2字节对齐*/

typedef struct STest1 

char ch1; 
long lo1; 
char ch2; 
} test1; 
typedef struct STest2 

char ch3; 
test1 test; 
} test2; 

此时 test1和test2分别为8,10


原创粉丝点击