C 语言结构体内存分配原则

原文: C 位域

   karma

结构体内存分配原则

原则一:结构体中元素按照定义顺序存放到内存中,但并不是紧密排列。从结构体存储的首地址开始 ,每一个元素存入内存中时,它都会认为内存是以自己的宽度来划分空间的,因此元素存放的位置一定会在自己大小的整数倍上开始。

原则二: 在原则一的基础上,检查计算出的存储单元是否为所有元素中最宽的元素长度的整数倍。若是,则结束;否则,将其补齐为它的整数倍。

测试实例:

#include <stdio.h>

typedef struct t1{
    char x;
    int y;
    double z;
}T1;

typedef struct t2{
    char x;
    double z;
    int y;
}T2;

int main(int argc, char* argv[])
{
    printf("sizeof(T1) = %lu\n", sizeof(T1));
    printf("sizeof(T2) = %lu\n", sizeof(T2));

    return 0;
}

输出:

sizeof(T1) = 16
sizeof(T2) = 24

解析

sizeof(T1.x) = sizeof(T2.x) = 1; 
sizeof(T1.y) = sizeof(T2.y) = 4; 
sizeof(T1.z) = sizeof(T2.z) = 8;

T1: 若从第 0 个字节开始分配内存,则 T1.x 存入第 0 字节,T1.y 占 4 个字节,由于第一的 4 字节已有数据,所以 T1.y 存入第 4-7 个字节,T1.z 占 8 个字节,由于第一个 8 字节已有数据,所以 T1.z 存入 8-15 个字节。共占有 16 个字节。

T2: 若从第 0 个字节开始分配内存,则 T1.x 存入第 0 字节,T1.z 占 8 个字节,由于第一的 8 字节已有数据,所以 T1.z 存入第 8-15 个字节,T1.y 占 4 个字节,由于前四个 4 字节已有数据,所以 T1.z 存入 16-19 个字节。共占有 20 个字节。此时所占字节不是最宽元素(double 长度为 8)的整数倍,因此将其补齐到 8 的整数倍,最终结果为 24。

更多解析

  xkl

补充楼上 @karma,位域的内存大小测试

// 位域内存测试
#include <stdio.h>
struct ONE_BYTE
{
    unsigned char _bool : 1;
    unsigned char del_flag : 1;
    unsigned char status : 4;
} one_byte;

struct TWO_BYTE
{
    unsigned char ccc1 : 4;
    unsigned char ccc2 : 4;
    unsigned char ccc3 : 4;
    unsigned char ccc4 : 4;
} two_byte;

struct THREE_BYTE
{
    unsigned char ccc1 : 4;
    unsigned char ccc2 : 4;
    unsigned char ccc3 : 4;
    unsigned char ccc4 : 4;
    unsigned char ccc5 : 4;
} three_byte;

struct FOUR_BYTE
{
    unsigned int ccc1 : 16;
    unsigned int ccc2 : 16;
} four_byte;


struct EIGHT_BYTE
{
    unsigned char ccc1 : 1;
    unsigned int ccc2 : 1;
} eight_byte;

int main(int argc, char const *argv[])
{
    printf("sizeof one_byte is : %lu\n", sizeof(one_byte));
    printf("sizeof two_byte is : %lu\n", sizeof(two_byte));
    printf("sizeof three_byte is : %lu\n", sizeof(three_byte));
    printf("sizeof four_byte is : %lu\n", sizeof(four_byte));
    printf("sizeof eight_byte is : %lu\n", sizeof(eight_byte));
    return 0;
}

输出结果为:

sizeof one_byte is : 1B
sizeof two_byte is : 2B
sizeof three_byte is : 3B
sizeof four_byte is : 4B
sizeof eight_byte is : 4B

由输出,可以验证以下结论:

(1)结构体内存分配原则:

  • 原则一:结构体中元素按照定义顺序存放到内存中,但并不是紧密排列。从结构体存储的首地址开始 ,每一个元素存入内存中时,它都会认为内存是以自己的宽度来划分空间的,因此元素存放的位置一定会在自己大小的整数倍上开始。
  • 原则二: 在原则一的基础上,检查计算出的存储单元是否为所有元素中最宽的元素长度的整数倍。若是,则结束;否则,将其补齐为它的整数倍。

(2)定义位域时,各个成员的类型最好保持一致,比如都用char,或都用int,不要混合使用,这样才能达到节省内存空间的目的。

忘记密码?

如何获取邀请码?

关闭