联合中设置字段位的最佳方法

时间:2015-10-15 20:54:24

标签: c++ c++11 bit-fields

我们说我有以下

struct S {
union {
    uint8_t flags;
    struct {
        uint8_t flag2bits : 2;
        uint8_t flag1bit : 1;
    };
};
};

S s;
s.flag2bits = 2;
s.flag1bit = 1; // this will wipe out the values of other bits

在不影响其他位字段的情况下,为特定位分配值的最佳方法是什么?

我可以转移然后再分配然后再移动但这意味着一旦有人改变了位字段的顺序,代码就会被破坏....

2 个答案:

答案 0 :(得分:4)

  

我可以转移然后再分配,然后再移动,但这意味着   一旦有人改变了位字段的顺序,代码就是   碎....

不,这并不意味着代码被破坏了。您可以更改任何位域(按任何顺序/您可以保留其中一些未设置)

在你的例子中:

S s;
s.flag2bits = 2;
s.flag1bit = 1;

更改flag2bits不会影响flag1bit中存储的值。

但是,您的问题可能与union中的struct有关。更改 flags 变量影响这两个位域,因为您将它们存储在单独的struct中。

我希望这个例子可以解释这个案例:

#include <iostream>
#include <cstdint>
struct S {
    union {
        uint8_t flags;
        struct {
            uint8_t flag2bits : 2;
            uint8_t flag1bit : 1;
        };
    };
};

int main(int argc, char *argv[]) {
    S s;
    s.flag2bits = 2;
    s.flag1bit = 1;

    std::cout << int(s.flag2bits) << int(s.flag1bit) << std::endl;
    s.flags = 4;  // As you are using union, at this point you are overwriting
                  // values stored in your (nested) struct
    std::cout << int(s.flag2bits) << int(s.flag1bit) << std::endl;

    return 0;
}

编辑:正如@ M.M指出的那样,it's undefined behavior to read from the member of the union that wasn't most recently written。虽然至少在clang-3.5上,上面的代码会打印出来:

21
01

说明了我想要做的一点(即覆盖联合字段)。

我会考虑从您的union代码中移除struct S,但我可能看不到您要实现的目标的全貌。

答案 1 :(得分:1)

C ++编译器将为您管理这些位。您可以根据需要设置值。只会设置适当的位。

你试过吗?