我最近不得不处理结构中的位域,并遇到了我无法解释的行为。
下面的struct应该是9个字节,根据个人的sizeof。但是对主结构进行 sizeof 会产生 10 个字节。
以下程序产生“10; 1 1 2 1 2 1 1 =9”
int main(){
struct{
uint8_t doubleoscillator;
struct{
char monophonic : 1;
char hold : 1;
char padding : 6;
} test;
int16_t osc1_multisound; //int
int8_t osc1_octave; // -2..1
int16_t osc2_multisound; //int
int8_t osc2_octave; // -2..1
int8_t intervall;
}osc;
std::cout << sizeof(osc) << "; ";
int a[7];
a[0] = sizeof(osc.doubleoscillator);
a[1] = sizeof(osc.test);
a[2] = sizeof(osc.osc1_multisound);
a[3] = sizeof(osc.osc1_octave);
a[4] = sizeof(osc.osc2_multisound);
a[5] = sizeof(osc.osc2_octave);
a[6] = sizeof(osc.intervall);
int total = 0;
for(int i=0;i<7;i++){
std::cout << a[i] << " ";
total += a[i];
}
std::cout << " = " << total << std::endl;
return 0;
}
为什么结构体内部变量的各个 sizeof() 之和与 osc
结构体的 sizeof() 产生不同的结果?
最佳答案
主要出于性能原因,在结构的每个成员之前添加填充,以在结构的内存布局中对齐所述成员。因此,ocs2_multisound 之前可能有一个填充字节,以确保它出现在结构中的字节数是 2 的倍数(因为 int16_t 的对齐方式为 2) .
此外,完成所有这些操作后,结构的总大小将填充为其最严格对齐要求的倍数(即任何保留字段的最高对齐方式)。这是这样的,例如所述类型的数组的元素将全部正确对齐。
可以在编译时通过 alignof(T)
检查类型的对齐情况,其中 T
是类型。
在这种情况下,大小的增加是不可避免的,但减少填充字节的常见建议是按降序排列对结构成员进行排序。这是因为下一个项目可以保证正确对齐,而不需要填充,因为前一个字段要么是相同的对齐方式,要么是更严格的对齐方式。因此,如果添加任何填充,也只是填充结构的总大小,而不是(浪费)字段之间的填充。
如今进行调整的原因主要是为了效率。在支持它的硬件上读取未对齐的内存块通常会慢两倍左右,因为它实际上是在读取它周围的两个内存块并提取它需要的内容。然而,如果您尝试读/写未对齐的内存,也有一些硬件根本无法工作。此类硬件通常会在此事件中触发硬件异常。
关于c++ - 使用位域的结构大小不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55407994/