数据结构中的数据变量是按定义的先后顺序来排放的,第一个数据变量的起始地址就是数据结构的起始地址。结构体的成员变量要对齐排放,并且结构的长度必须为成员中自身对齐值最大的那个值的整数倍,不够就补空字节

例子分析:

分析例子B:
struct B
{
    char b;
    int a;
    short c;
};
假设B从地址空间0x0000开始存放,char类型1个字节,int类型4个字节,short类型2个字节,所以对齐值为4。在0x0000存放的是b,之后补上3个空字节,在0x0004到0x0007这四个连续的空间存放的是a,在0x0008到0x0009这两个字节空间中,存放的是c,根据结构体长度整除对齐值的规则,在0x000A到0x000B中补上空字节就满足对齐了。



结构体自身的对齐

1.如果没有明确写上paragma pack(x),结构体自身就按照结构体里最大成员长度对齐 

比如 
typedef struct _FILE_BASIC_INFORMATION 

    LARGE_INTEGER    CreationTime;    //8字节 
    LARGE_INTEGER    LastAccessTime;  //8字节 
    LARGE_INTEGER    LastWriteTime;   //8字节 
    LARGE_INTEGER    ChangeTime;      //8字节 
    USHORT        FileAttributes;  //4字节 
}FILE_BASIC_INFORMATION;
整个结构体按sizeof(LARGE_INTEGER)对齐
比如 
pragma pack(4) 
typedef struct _FILE_BASIC_INFORMATION 

    LARGE_INTEGER    CreationTime;    //8字节 
    LARGE_INTEGER    LastAccessTime;  //8字节 
    LARGE_INTEGER    LastWriteTime;   //8字节 
    LARGE_INTEGER    ChangeTime;      //8字节 
    USHORT        FileAttributes;  //4字节 
}FILE_BASIC_INFORMATION;
比如 
pragma pack(8) 
typedef struct _x 

    char a; 
    short b; 
}x; 
sizeof(x) = 4 (按sizeof(short)对齐)
struct C
{
    char b;
    int a;
    short c;
};
第一个变量b的自身对齐值为1,指定对齐值为2,所以,其有效对齐值为1,假设C从0x0000开始,那么b存放在0x0000,符合 0x0000%1= 0;第二个变量,自身对齐值为4,指定对齐值为2,所以有效对齐值为2,所以顺序存放在0x0002、0x0003、0x0004、0x0005四个连续字节中,符合0x0002%2=0。第三个变量c的自身对齐值为2,所以有效对齐值为2,顺序存放在0x0006、0x0007中,符合 0x0006%2=0。所以从0x0000到0x00007共八字节存放的是C的变量。又C的自身对齐值为4,所以C的有效对齐值为2。又8%2=0,C 只占用0x0000到0x0007的八个字节。所以sizeof(struct C)=8。

sizeof(FILE_BASIC_INFORMATION) = 40 

2.如果明确写上paragma pack(x)则又分为两种情况:

a.如果x小于结构体长度最大的成员的长度 则按x对齐 

sizeof(FILE_BASIC_INFORMATION) = 36(按4对齐而不是按sizeof(LARGE_INTEGER)

b.如果x大于结构体长度最大的成员的长度 则按结构体里长度最长成员长度对齐 

举例:

#pragma pack (2)

总之,编译器是按照什么样的原则进行对齐的?成员对齐有一个重要的条件:即每个成员按自己的方式对齐。其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里默认是8字节)中较小的一个对齐。并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节。



​http://blog.sina.com.cn/s/blog_74a271040100u15p.html​