C语言中结构体的对齐规则、sizeof(结构体变量)

1、以最大类型的字节为单位

        结构体(struct)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存放在offset为该数据成员大小的的整数倍的地方(比如int在32位机器上为4字节,则要从四字节的整数倍开始存储)。考虑如下一段代码:

#include 

struct example_1
{
    int a;
    char b;
    short c;
}A;

struct example_2
{
    char e[2];
    int f;
    double g;
    short h;
}B;


int main(int argc, char *argv[])
{

    printf ("sizeof(struct example_1) = %d\n", sizeof(A));
    printf ("sizeof(struct example_2) = %d\n", sizeof(B));

    return 0;

}

      上述代码的输出结果为:sizeof(struct example_1) = 8

                                              sizeof(struct example_2) = 24

        对于结构体A来说,其成员里面最大长度的类型为int型,在32位机器上为4Byte。所以该结构体以4字节对齐。

A:对于成员a来说首先会放到offset为0的地方占用四个字节。

      对于b,成员b为char类型,占用1个字节。所以:1  *  0 = 0,此时offset = 0的地方存放有成员a,所以不能存放成员b;1 * 2 = 2,此时offset = 2的地方也是a的存放地方,等等。指导1 * 4 = 4,此时offset = 4,此时该地址偏移的地方没有存放成员,可以用来存放成员,占用1字节的空间。

      对于c,c为short类型,占用2字节。所以:2 * 0 = 0,此偏移地址存放a;2 * 1 = 2, 此偏移地址存放a;2 * 2 = 4, 此偏移地址存放变量b;2 * 3 = 6,此时该偏移地址没有存放内容,可以用来存放变量c,占用2个字节。

        注意:结构体(struct)占用内存空间的大小,是其最大成员数据类型的整数倍。

a a a a
b * c c

        对于结构体B来说,其成员里面的最大类型为double类型,占用8字节空间。所以该结构体以8字节对齐。

B:对于成员e,数据类型为char类型,占用1个字节。所以,1 * 0  = 0, 没有被占用可以用来存放e,由于成员e是数组类型的成员,所以连续进行存放。

        f成员,数据类型为int类型,占用4个字节。所以,4 * 0 = 0, 该空间被占用;4 * 1 = 4, 该空间没有被占用,所以用来存放f成员。

        g成员,数据类型为double,占用8个字节。所以,8 * 0 = 0, 该空间被占用;8 * 1 = 8,该空间没有被占用,用来存放g。

        h成员,数据类型为short类型,占用2个自己。所以,直到,2 * 8 = 16,该空间没有被占用,用来存放h成员。

e e * * f f f f
g g g g g g g g
h h * * * * * *

2、结构体嵌套结构体时,以两者最大的数据类型对齐。

        如果一个结构体B嵌套一个结构体A,结构体A应从offset为A内部最大成员的整数倍的地方开始存储。考虑如下,代码。

#include 

struct example_1
{
    int a;
    double b;
    float c;
}A;

struct example_2
{
    char e[2];
    int f;
    double g;
    short h;
    struct example_1  i;
}B;


int main(int argc, char *argv[])
{

    printf ("sizeof(struct example_2) = %d\n", sizeof(B));

    return 0;

}

        上述程序的运行结果是:sizeof(struct example_2) = 48

        对于结构体B来说,B里面嵌套了结构体A,两者最大类型均为double类型,所以以8字节对齐。

B:

        e,类型为char类型,占用一个字节, 0 * 1 = 0, 该偏移地址没有被占用,所以用来存放e

        f,int类型,四个字节,4 * 1 = 4,该地址偏移没有被占用,可以用来存放f。

        g,double类型,占用8个字节,8 * 1 = 8, 该地址偏移没有被占用,可以用来存放g。

        h,short类型,占用2个字节,2 * 8 = 16,该地址偏移没有被占用,可以用来存放h。

        接下来,是其结构体成员 A,由于不能在B的结构体后面直接存放结构体A的成员,必须等A结构体存放完整,而且占用空间为结构体A对齐长度的整数倍之后的地址偏移,存放A的成员。

A:

        a,int类型,占用4字节空间,24 + 4 * 0 , 该地址偏移没有被占用,可以用来存放a。

        b , double类型,占用4字节空间, 24 + 8 * 1 , 该地址没有被占用,可以用来存放b。

        c,float类型,占用4字节空间, 24 + 4 * 3, 该地址没有被占用,可以用来存放c。

e e * * f f f f
g g g g g g g g
h h * * * * * *
a a a a * * * *
b b b b b b b b
c c c c * * * *

注意:结构体成员的位置的先后顺序不同,占用的空间的大小也会不同。

你可能感兴趣的:(C,c语言)