位域中的字节对齐

问题描述 投票:0回答:1

在 cppreference article 中关于位字段的内容:

#include <bit>
#include <cstdint>
#include <iostream>
 
struct S
{
    // will usually occupy 2 bytes:
    unsigned char b1 : 3; // 1st 3 bits (in 1st byte) are b1
    unsigned char    : 2; // next 2 bits (in 1st byte) are blocked out as unused
    unsigned char b2 : 6; // 6 bits for b2 - doesn't fit into the 1st byte => starts a 2nd
    unsigned char b3 : 2; // 2 bits for b3 - next (and final) bits in the 2nd byte
};
 
int main()
{
    std::cout << sizeof(S) << '\n'; // usually prints 2
 
    S s;
    // set distinguishable field values
    s.b1 = 0b111;
    s.b2 = 0b101111;
    s.b3 = 0b11;
 
    // show layout of fields in S
    auto i = std::bit_cast<std::uint16_t>(s);
    // usually prints 1110000011110111
    // breakdown is:  \_/\/\_/\____/\/
    //                 b1 u a   b2  b3
    // where "u" marks the unused :2 specified in the struct, and
    // "a" marks compiler-added padding to byte-align the next field.
    // Byte-alignment is happening because b2's type is declared unsigned char;
    // if b2 were declared uint16_t there would be no "a", b2 would abut "u".
    for (auto b = i; b; b >>= 1) // print LSB-first
        std::cout << (b & 1);
    std::cout << '\n';
}

我没有成功地在网上搜索为什么如果

b2
被声明为
uint16_t
那么
b2
会邻接
u
,并且
b2
不会字节对齐。

c++ bit-fields
1个回答
1
投票

请注意,文章说的是“通常”和“可能的输出”。

某些编译器(例如示例中考虑的编译器)不会在存储单元之间拆分位域。因此,如果以

unsigned char
为单位存储,则 3 + 2 + 6 位将无法容纳。但如果您使用 16 位字,它们将会都适合。

标准具体

[注 1: 位域在某些机器上跨分配单元,而不是 在其他人身上。在某些机器上,位域是从右到左分配的, 对其他人从左到右。 — 尾注]

如果您想要任何类型的可移植性,这使得它们不再那么有用。但是,如果您使用它们来建模硬件寄存器,那么可移植性可能就不再是问题了。

© www.soinside.com 2019 - 2024. All rights reserved.