转载--结构对齐

关于C语言中的结构体对齐问题
1,比如:

struct{
short a1;
short a2;
short a3;
}A;
struct{
long a1;
short a2;
}B;
sizeof( A)=6, sizeof( B)=8,为什么?
注:sizeof(short)=2,sizeof(long)=4

因为:“成员对齐有一个重要的条件,即每个成员按自己的方式对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里默认是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节.”(引用)
结构体A中有3个short类型变量,各自以2字节对齐,结构体对齐参数按默认的8字节对齐,则a1,a2,a3都取2字节对齐,则sizeof(A)为6,其也是2的整数倍;
B中a1为4字节对齐,a2为2字节对齐,结构体默认对齐参数为8,则a1取4字节对齐,a2取2字节对齐,结构体大小6字节,6不为4的整数倍,补空字节,增到8时,符合所有条件,则sizeof(B)为8;

可以设置成对齐的
#pragma pack(1)
#pragma pack(push)
#pragma pack(1)
struct{
short a1;
short a2;
short a3;
}A;
struct{
long a1;
short a2;
}B;
#pragma pack(pop)        结果为sizeof( A)=6,sizeof( B)=6

************************

2,又如:

#pragma pack(8)
struct S1{
    char a;
    long b;
};
struct S2 {
    char c;
    struct S1 d;
    long long e;
};
#pragma pack()
sizeof(S2)结果为24.
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐.
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节.
S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8;
S2  中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时, 已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样, 一共使用了24个字节.
                               a      b
S1的内存布局:1***, 1111,
                          c      S1.a    S1.b             e
S2的内存布局:1***, 1***,   1111, ****11111111

这里有三点很重要:
1.每个成员分别按自己的方式对齐,并能最小化长度
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐

补充一下,对于数组,比如:
char a[3];这种,它的对齐方式和分别写3个char是一样的.也就是说它还是按1个字节对齐.
如果写: typedef char Array3[3];
Array3这种类型的对齐方式还是按1个字节对齐,而不是按它的长度.
不论类型是什么,对齐的边界一定是1,2,4,8,16,32,64....中的一个.

转自:http://blog.chinaunix.net/u/11768/showart.php?id=70557

一道关于结构对齐的题目
struct{
        short a1;
        short a2;
        short a3;
}A;
struct{
        long a1;
        short a2;
}B;
问:为什么sizeof(A)为6,sizeof(B)为8。
这是一个关于结构数据对齐的题,其原因是为了加快CPU的存取速度,编译器在处理数据时经常把结构变量中的成员的大小按照4或8的倍数计算,叫数据对齐(data alignment)。其对齐规则为:结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节。这也就是为什么会出现这个现象的原因。因为sizeof(short)为2,sizeof(int)为4,sizeof(long)也为4。对于开头题目中的Struct B,因为long长为4,short长为2,因为short会补跳成为4,因此为8。而对于Strutc A,每个成员均为2,因此不需要补空字节。
下面另一个例子:
#include <stdio.h>

struct{
        short a1;
        short a2;
        short a3;
        long a4;
}A;
struct{
        long a1;
        int a3;
}B;
int main()
{
        printf("sizeof(short)=%d sizeof(long)=%d sizeof(int)=%d/n", sizeof(short), sizeof(long
), sizeof(int));
        printf("sizeof(A)=%d sizeof(B)=%d/n", sizeof(A), sizeof(B));
        return 0;
}
struct A长为12,因为a1和a2一起长度为4,a3为2,long为4,因为需要为a3补空字节,使其长度变为4。
Struct B长为8.
再看另一个结构:
struct{
        short a1;
        long a5;
        short a2;
        long a6;
        short a3;
        long a4;
}A;
其长度为24,因为a1长为2,a5长为4,因此a1需要补成4,其余字节同样。
但当我们把struct A调整为
struct{
        short a1;
        short a2;
        short a3;
        long a4;
        long a5;
        long a6;
}A;
其长度就变为20了。
说实在话,这个问题是我以前根本没注意的问题。
但是如果我们在前面加上#pragma pack(1),我们会发现编译不会进行对齐的操作。因为成员对齐有一个重要的条件,即每个成员按自己的方式对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节.”

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值