结构体内存对齐

结构体内存对齐,主要是为了CPU能更快速的提取数据


所谓的对齐,指结构体及其成员的内存起始地址address应为要对齐大小X的倍数,

        即address = kX


假设 n 为编译器设定的对齐大小, item为结构体中成员类型,那么实际对齐的大小值,

计算如下:

X = min(n, sizeof(item))

-------------------------------------------------------

举例:

例1:

enum ENUM_DATA{IntData, CharData, LongData};
struct Item
{
    char ItemChar1[30];
    ENUM_DATA ItemEnum;
    char ItemChar2[50];
    int ItemInt;
};

sizeof(struct Item)等于多少?

分析如下:

1.结构体模式模式按成员中最大长度类型进行内存对齐,

   struct Item中最大长度类型为int,长度为4

2.假设第一成员的起始地址为0,那么:

    ItemChar1 的类型长度为1,根据X = min(n, sizeof(ItemChar1)),即X = min(4, 1) = 1,按1对齐

                       所以,内存地址空间范围为 0~29, 占30个Byte;

   ItemEnum 的类型长度为4,根据X = min(n, sizeof(ItemEnum)),即X = min(4, 4) = 4,按4对齐

                      由于ItemChar1的结尾内存地址为29,所以下一个成员应该从30开始,

                      但是30不是4的倍数,往后偏移到32才是4的倍数,

                      所以ItemEnum的起始内存地址应该是32,

                      所以,内存地址空间范围为 32~35, 占4个Byte;

   ItemChar2 的类型长度为1, X = min(4, 1) = 1

                      所以,内存地址空间范围为 36~85, 占50个Byte;

   ItemInt 的类型长度为4,X = min(4, 4) = 4

                      起始地址应该是86,但是86非4的倍数,最靠近的88才是4的倍数,

                      所以起始地址偏移到88的位置

                      所以,内存地址空间范围为 88~91, 占4个Byte;

3. 由上一步计算得到结构体的内存空间范围为0~91,即大小为92,

    而92已经是4的倍数,即所谓的已经对齐

    所以该结构体的大小: sizeof(struct Item)等于92

-------------------------------------------------------

例2:

struct A{
	int i;
	int j;  
	short s;
	char c;
};
分析如下:

1.结构体A的最大长度类型int,大小为4

2.假设起始地址为0

    i 的类型int,    大小为4, min(4, 4) = 4, 按4对齐,内存地址空间为 0~3

    j 的类型int,    大小为4, min(4, 4) = 4, 按4对齐,内存地址空间为 4~7 (4已是4的倍数)

   s 的类型short,大小为2,min(4, 2) = 2, 按2对齐,内存地址空间为 8~9 (8已是2的倍数)

   c 的类型char, 大小为1, min(4, 1) = 1, 按1对齐,内存地址空间为 10  (10已是1的倍数)
3. 结构体A的地址空间范围为0~10, 大小为11, 

    但由于要按4对齐,11非4的倍数,最靠近的12才是

    所以结构体A的大小应该是12

-------------------------------------------------------

例3:

struct A
{
	char a;
	int b;
	double c;
	char d;
};
1. 结构体最大长度类型double,长度为8

2. 假设结构体起始地址为0

    a 的类型char大小为1,1小于8,按1对齐,地址空间范围为 0

    b 的类型int   大小为4,4小于8,按4对齐,

       由于接下来的起始地址1不是4的倍数,所以取4做起始地址

       即b的地址空间范围应该是4~7

    c 的类型double 大小为8,8等于8,按8对齐,

       接着的起始地址应该是8,已经是8的倍数,

       所以c的地址空间范围应该是 8~15

    d 的类型char大小为1,1小于8,按1对齐,地址空间范围16

3. 结构体地址空间范围0~16, 大小为17,

    17不是8的倍数,最靠近的为8的倍数的数应该是24,

     所以该结构体大小为24

-------------------------------------------------------

测试:

test.c

#include <stdio.h>

struct st_a {
	int a;
	char b;
	char c;
};

struct st_b {
	char b;
	short c;
	int a;
};

struct st_c {
	char b;
	int a;
	short c;
};

int main(int argc, char* argv[])
{
	struct st_a a;
	struct st_b b;
	struct st_c c;

	printf("st_a size:%d\n", sizeof(a));
	printf("       &a:%ld\n", &a.a);
	printf("       &b:%ld\n", &a.b);
	printf("       &c:%ld\n", &a.c);

	printf("st_b size:%d\n", sizeof(b));
	printf("       &b:%ld\n", &b.b);
	printf("       &c:%ld\n", &b.c);
	printf("       &a:%ld\n", &b.a);

	printf("st_c size:%d\n", sizeof(c));
	printf("       &b:%ld\n", &c.b);
	printf("       &a:%ld\n", &c.a);
	printf("       &c:%ld\n", &c.c);

    return 0; 
}

gcc -o t test.c


./t

输出:

st_a size:8
       &a:140733530861264
       &b:140733530861268
       &c:140733530861269
st_b size:8
       &b:140733530861248
       &c:140733530861250
       &a:140733530861252
st_c size:12
       &b:140733530861232
       &a:140733530861236
       &c:140733530861240

参考文章:

http://blog.csdn.net/hbyh/article/details/2061471

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值