最近,我不得不处理结构中的位域,并且遇到了我无法解释的行为。
以下结构应为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()有不同的结果?
答案 0 :(得分:2)
主要出于性能原因,在结构的每个成员之前添加填充以使该成员在结构的内存布局中对齐。因此,ocs2_multisound
可能在其前面有一个填充字节,以确保它以2的倍数出现在结构中的字节数处(因为int16_t
的对齐方式为2)。
此外,在完成所有操作之后,结构的总大小将填充为其最严格的对齐要求(即,任何保留字段的最高对齐)的倍数。就是这样所述类型的数组的所有元素都将正确对齐。
可以在编译时通过alignof(T)
来检查类型的对齐方式,其中T
是类型。
在这种情况下不可避免地会增加大小,但是减少填充字节的常见建议是按降序排列顺序对结构成员进行排序。这是因为,由于前一个字段是相同的对齐方式或更严格的对齐方式,因此保证了下一个项目正确对齐而不需要填充。因此,如果添加了任何填充,则只会填充结构的总大小,而不是在字段之间填充(浪费)。
如今,保持一致的原因主要是为了提高效率。在支持它的硬件上读取未对齐的内存块的速度通常大约是它的两倍,因为它实际上是在读取它周围的两个内存块并提取所需的内容。但是,如果尝试读取/写入未对齐的内存,则还有一些硬件根本无法工作。这种硬件通常会在此事件中触发硬件异常。