c++ - 使用位域的结构大小不正确

标签 c++ struct bit-fields

我最近不得不处理结构中的位域,并遇到了我无法解释的行为。

下面的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/

相关文章:

C++ 通过指针访问私有(private)函数

c++ - 如何强制将常量 C 表达式求值用作 .S 文件中的常量?

c - 在函数调用期间结构更改的 union 内的结构

c - malloc 位字段值到 c 中的数组

c# - 字节数组作为 C# 中的位域?

python - 安装Python3.6版本的Boost-Python3

c++ - SQL 解析器库 - 从查询中获取表名

c - 通过 SunRPC 发送带缓冲区的链表 (c)

c - 带位字段的 QR 编码

c++ - 如何使用位字段将数据从二进制文件复制到结构中?