有关内存对齐的问题

两大规则:

1:某个成员距离首位置的偏移量最小是该成员大小的一倍。
2:所有成员的大小之和应该是最大成员大小的整数倍。

为什么要内存对齐?点这里

来段代码解释下:

#include<stdio.h>

struct student1
{
    char  a;
    short b;
    int   c;
}stu1;

struct student2
{
    char  a;
    int   b;
    short c;
}stu2;

int main()
{
    printf("sizeof(stu1) : %d\n",(int)sizeof(stu1));
    printf("sizeof(stu2) : %d\n",(int)sizeof(stu2));
    return 0;
}

这里写图片描述

我们接下来就来解释为什么stu1和stu2分别是8和12,主要还是我们的两个规则:

注意:下面的表示方法,例如short b 就会在两个字节中填b,表示占用两个字节*

对于stu1来说,a是char类型的,占1个字节.如图:
这里写图片描述
b是short类型的,占2个字节,由于规则1,某个成员距离首位置的偏移量最小是该成员的1倍,但是此时b距离首位置只有a这一个字节,所以补一个字节,如图:
这里写图片描述
再说到c为一个int类型的,占用4个字节,我们用规则1去验证,现在它距离首位置的偏移量是4,并且它自己也占用4个字节,刚好是一倍,满足规则1,再来看规则2,所有成员的大小之和应该是最大成员大小的整数倍,现在c为int类型,加上前面的4个字节,一共是8个字节,是最大成员c的字节数的2倍,满足规则2,所以就直接将c放在后面.如图:
这里写图片描述
那么对于stu2来说呢,
首先char a还是一样的,a占用一个字节.如图:
这里写图片描述
再说b,b是一个int类型的变量,首先根据我们的规则1,距离首位置的偏移量至少是该成员的一倍,所以应该补3个位置,如图:
这里写图片描述
再说short c,根据规则1,现在的成员偏移量为8,c的大小为2,满足规则1,再来看规则2,目前我们所有成员的大小为10,并不满足目前成员大小为最大成员(int b)大小的整数倍,所以需要再补两个字节,总大小构成12,就是4的整数倍了,如图:
这里写图片描述

好,基本上就是这样,但是有没有思考过我在最后补的两个字节为什么要补在最后呢,难道不会是下面这样吗?
这里写图片描述
好,带着这个问题,我们来看看下面的这段代码:

#include<stdio.h>


struct node1
{
    int  a;
    int  b;
    int  c;
};
struct node2
{
    char  a;
    char  b;
    short c;
    int   d;
};
int main()
{
    struct node1 s1 = {3,5,6};
    struct node2 s2 = {3,5,6,99};
    struct node *p1 = &s1;
    struct node *p2 = &s2;
    printf("%d\n",*(int *)p1);
    printf("%d\n",*(int *)p2);
}

这里写图片描述
恩,这个执行结果有点糟糕啊,第一个执行结果到是没什么问题,但是第二个394499怎么解释呢.
原因就要牵扯到内存对齐的问题,再次回忆下内存对其两个原则,一个最小,一个最大,一个最小:某个成员目前的偏移量最小是这个成员的一倍,一个最大:所有成员的大小之和是最大成员的整数倍.
现在再来分析:我分别给a,b,c赋值3,5,6.即分别占用1,1,2个字节,总共就是4个字节,即一个int,那么我最后printf中的值肯定就是这4个字节组成的,按照低地址存入,高地址输出的原则,所以在内存中会是这样计算,6*2^16+5*2^8+3*2^0 = 394499,(2^16是宏观把握的结果)如图:
这里写图片描述
所以补的位置就是上面例子的位置,而不是先补后加数据,原因上面的例子已经得到很好的验证,至于为什么要这样,不是补在低位呢,我还没研究这么深,搞懂再说吧……

版权声明:本文为博主原创文章,未经博主允许不得转载。

posted on 2015-10-21 18:26  杨博东的博客  阅读(129)  评论(0编辑  收藏  举报

导航