位域和联合的有效使用

Valid use of bit-fields and unions

我写这段代码只是为了好玩:

union {
    struct {
        bool a : 1;
        bool b : 1;
        bool c : 1;
        bool d : 1;
        bool e : 1;
        bool f : 1;
        bool g : 1;
        bool h : 1;
    } a;
    uint8_t b;
} uni {0}; // sets .a bits to false

// union size  : 1 byte

我可以单独切换每一位:

uni.a.a = true;
uni.a.d = true;

cout << bitset<8>(uni.b) << endl; // Prints 000010001

并且还使用位掩码:

uni.b = 0b00001000;

if(uni.a.a) cout << "a";
if(uni.a.b) cout << "b";
if(uni.a.c) cout << "c";
if(uni.a.d) cout << "d";
if(uni.a.e) cout << "e";
if(uni.a.f) cout << "f";
if(uni.a.g) cout << "g";
if(uni.a.h) cout << "h";
// prints 'd'

我知道还有其他方法可以做到这一点(按位运算),但我喜欢这种设计。我的问题是:就可靠性和性能而言,这是对位域和联合的良好使用吗?

My question is: is this a good use of bitfields and unions, in terms of reliability and performance?

就性能而言,您正在做的事情可能与将要达到的一样好,至少在位级别访问内存方面是这样。

就可靠性而言,它可能适用于大多数现代系统。冒着听起来像语言律师的风险,以下是一些可能在不同系统中产生不同结果的领域:

  1. sizeof(bool)不保证为1,即bool可以存储在大于一个字节的内存中。我不知道有哪个现代系统 bool 不是一个字节的大小,但你可以想象一个旧的或错误的实现使得 bool 与 [=14] 的大小相同=].这本质上会影响你的 union.
  2. 访问 union 的不同成员变量会导致未定义的行为
  3. 跨系统的字节顺序可能不同(例如,大端或小端),导致 union 的成员代表 MSB 的差异。
  4. 从技术上讲,该实现可以在一个字节内以任何顺序布置位域的各个位。我知道的每个实现都会按照您在 struct 中定义的顺序对它们进行排序,但这不一定会发生。
  5. 该实现可以在 struct 的各个成员之间插入填充,以便各个位位于内存的不同字节中。同样,我所知道的所有实现都不会这样做,但它可能会发生。

我认为您不必担心上述问题。但是,就涵盖所有可能出错的内容而言,我认为上面的列表很好地涵盖了真正 odd-ball 如果您真的搜索有点不同的实现可能会遇到的情况。