C 布尔的填充差异
有人能解释为什么uint8\u t填充了3个字节,而bool只填充了1个字节。这是因为在这种情况下,C 布尔的填充差异,c,C,有人能解释为什么uint8\u t填充了3个字节,而bool只填充了1个字节。这是因为在这种情况下,float(请求4字节对齐)在uint8之后,而uint16\u t(请求2字节对齐)在bool之后 交换它们将导致交换填充的数量 struct home { uint32_t calss; uint8_t name; float keyl; bool flag; uint16_t me; }; 第一个字段填充了3个字节,因为下一个字段(afloat)需要四字节对齐,因此需要三个字节
float
(请求4字节对齐)在uint8
之后,而uint16\u t
(请求2字节对齐)在bool
之后
交换它们将导致交换填充的数量
struct home
{
uint32_t calss;
uint8_t name;
float keyl;
bool flag;
uint16_t me;
};
第一个字段填充了3个字节,因为下一个字段(a
float
)需要四字节对齐,因此需要三个字节将其对齐到四个字节的倍数。第二个字段(bool
)有一个字节的填充,原因相同:下一个字段(uint16\u t
,16位宽)需要2字节对齐,因此只需要一个字节即可获得2字节对齐
对于最后的填充,您将struct
对齐方式计算为结构中最大字段的最大对齐方式,并包括填充以使此类struct
s的数组正确对齐。结构的sizeof
将反映这一最终对齐,因此一组这样的结构将使所有单元对齐,只对齐第一个单元
如果您对
struct
字段进行重新排序,使两个单字节字段在一起,在两字节数据之前或之后,那么您将得到一个没有间隙的结构。这是因为在一个字段对齐的字段之后还有另一个一字节字段,而下一个字段(两字节字段)已经对齐到2的倍数地址,因此不需要填充。在2字节字段之后,对齐已对齐4字节,因此下一个字段将紧跟其后。这取决于编译器、编译器选项和处理器体系结构。你应该提供这些信息。是什么让你这么认为的?注意:一般来说,为了减少填充,我建议使用gcc
/clang
中的-Wpadded
进行编译,每当编译器添加填充时都会发出警告。那么这就是一个简单的重新安排问题。
#include <stdio.h>
#include <stdbool.h>
#include <inttypes.h>
struct home
{
uint32_t calss;
uint8_t name;
float keyl;
bool flag;
uint16_t me;
};
struct home2
{
uint32_t calss;
uint8_t name;
uint16_t keyl;
bool flag;
float me;
};
int main(void) {
struct home h;
struct home2 h2;
printf("home:\n");
printf("calss : %p\n", (void*)&h.calss);
printf("name : %p\n", (void*)&h.name);
printf("keyl : %p\n", (void*)&h.keyl);
printf("flag : %p\n", (void*)&h.flag);
printf("me : %p\n", (void*)&h.me);
printf("home2:\n");
printf("calss : %p\n", (void*)&h2.calss);
printf("name : %p\n", (void*)&h2.name);
printf("keyl : %p\n", (void*)&h2.keyl);
printf("flag : %p\n", (void*)&h2.flag);
printf("me : %p\n", (void*)&h2.me);
return 0;
}
home:
calss : 0x7ffcd0f9b4a0
name : 0x7ffcd0f9b4a4
keyl : 0x7ffcd0f9b4a8
flag : 0x7ffcd0f9b4ac
me : 0x7ffcd0f9b4ae
home2:
calss : 0x7ffcd0f9b490
name : 0x7ffcd0f9b494
keyl : 0x7ffcd0f9b496
flag : 0x7ffcd0f9b498
me : 0x7ffcd0f9b49c