C语言结构体的存储空间分配

一. 结构体在内存中是如何实际存储的呢?

1.如果某个机器的整型值长度为4个字节,那么结构体的起始存储位置必须能被4整除

2.编译器按照成员列表的顺序一个接一个地给每个成员分配内存。其中对于各个成员,编译器根据其类型分配赋予对其要求,比如char成员,按地址能被1整除对齐;short成员,按地址能被2整除对齐;int成员,按地址能被4整除对齐......

3.编译器在存储结构体成员时,为了满足各个成员的正确边界对齐要求,会在成员之间添加用于填充的额外内存空间。

4.举个例子:

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

内存布局如下:

二. 结构体成员重排与节约内存

有时,我们有充分的理由,决定不对结构体的成员进行重排以减少因对齐带来的空间损失。例如,我们可能想把相关的结构成员存储在一起,提高程序的可维护性和可读性。但是,如果不存在这样的理由,结构的成员应该根据他们的边界需要进行排列,减少因边界对齐而造成的内存损失。

特别的,在某些情况下,我们必须按照严格的边界对齐要求来定义结构体以获取正确的数据,比如:考虑解析BMP图片的代码例子。

RGB24(RGB888)生成BMP图片代码_denglin12315的博客-CSDN博客

 关于header的定义1(包括3个部分):

1. 2字节的字符
2. BITMAPFILEHEADER部分
typedef struct                       /**** BMP file header structure ****/  
{  
    unsigned int   bfSize;           /* Size of file */  
    unsigned short bfReserved1;      /* Reserved */  
    unsigned short bfReserved2;      /* ... */  
    unsigned int   bfOffBits;        /* Offset to bitmap data */  
} BITMAPFILEHEADER1;

3.BITMAPINFOHEADER部分
typedef struct                       /**** BMP file info structure ****/  
{  
    unsigned int   biSize;           /* Size of info header */  
    int            biWidth;          /* Width of image */  
    int            biHeight;         /* Height of image */  
    unsigned short biPlanes;         /* Number of color planes */  
    unsigned short biBitCount;       /* Number of bits per pixel */  
    unsigned int   biCompression;    /* Type of compression to use */  
    unsigned int   biSizeImage;      /* Size of image data */  
    int            biXPelsPerMeter;  /* X pixels per meter */  
    int            biYPelsPerMeter;  /* Y pixels per meter */  
    unsigned int   biClrUsed;        /* Number of colors used */  
    unsigned int   biClrImportant;   /* Number of important colors */  
} BITMAPINFOHEADER1; 

 关于header的定义2:

typedef struct                       /**** BMP file info structure ****/  
{  
    char simbol[2]
    unsigned int   bfSize;           /* Size of file */  
    unsigned short bfReserved1;      /* Reserved */  
    unsigned short bfReserved2;      /* ... */  
    unsigned int   bfOffBits;        /* Offset to bitmap data */  
    unsigned int   biSize;           /* Size of info header */  
    int            biWidth;          /* Width of image */  
    int            biHeight;         /* Height of image */  
    unsigned short biPlanes;         /* Number of color planes */  
    unsigned short biBitCount;       /* Number of bits per pixel */  
    unsigned int   biCompression;    /* Type of compression to use */  
    unsigned int   biSizeImage;      /* Size of image data */  
    int            biXPelsPerMeter;  /* X pixels per meter */  
    int            biYPelsPerMeter;  /* Y pixels per meter */  
    unsigned int   biClrUsed;        /* Number of colors used */  
    unsigned int   biClrImportant;   /* Number of important colors */  
} BITMAPINFOHEADER2; 

这里直接说答案并提问: 为什么不能按照定义2的方式,而非要按照按照定义1的方式?定义2不是更简单直观吗?

答案提示:比较一下 2 + sizeof(BITMAPFILEHEADER1) + sizeof(BITMAPINFOHEADER1) 与

sizeof(BITMAPINFOHEADER2)的大小,标准bmp文件头的大小应该是和2 + sizeof(BITMAPFILEHEADER1) + sizeof(BITMAPINFOHEADER1)的值相等。出现以上差异的原因就是结构体对齐机制导致的。

三. 结构体相关的宏

1.sizeof()

2.offsetof(type, member)    ———  定义于stddef.h文件

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
结构体C语言中是一种用户自定义的数据类型,可以包含多个不同类型的数据成员。结构体的内存布局是按照成员的先后顺序存储的,而且每个成员的内存地址是连续的。 在C语言中,结构体的二进制表示是根据其成员的数据类型和内存布局来确定的。对于每个成员变量,都会有一定大小的内存空间来存储其值。在内存中,结构体的数据成员是按照其定义的顺序依次排列的,每个成员变量的内存地址是按照连续的方式分配的。 当我们将一个结构体对象写入磁盘或进行网络传输时,需要将结构体对象转换为二进制数据。这个过程称为序列化。在序列化结构体时,需要按照成员的内存布局和数据类型来将结构体中的数据逐个转换为对应的二进制表示。而在接收到二进制数据后,需要进行反序列化,将二进制数据还原为结构体对象。 在C语言中,可以使用指针来操作结构体对象的二进制数据。通过指针,可以获取结构体对象的内存地址,并直接对其进行操作。同时,也可以将指针强制类型转换为其他类型的指针,以便对结构体对象进行更灵活的操作。 总之,结构体C语言中的二进制表示是根据其成员的数据类型和内存布局来确定的,可以通过序列化和反序列化将结构体转换为二进制数据,并且可以使用指针来操作结构体对象的二进制数据。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

denglin12315

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值