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

Best way to set bits of fields in union

本文关键字:最佳 方法 字段 设置      更新时间:2023-10-16

假设我有以下内容

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

在不影响其他位域的情况下为特定位赋值的最佳方法是什么?

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

我可以移动,然后赋值,然后再移动,但这意味着一旦有人改变了位字段的顺序,代码就会被修改破碎的…

不,这并不意味着代码被破坏了。你可以随意改变位域(以任何顺序/你可以保留一些不设置)

在你的例子中:

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

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

然而,您的问题可能与您在struct中持有的union有关。更改 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;
}

EDIT: As @M。M指出,从union的成员中读取不是最近写入的数据是未定义的行为。尽管至少在clang-3.5上,上面的代码将打印:

21
01

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

我会考虑从您的struct S代码中删除union,尽管我可能看不到您想要实现的全部内容。

c++编译器将为您管理这些位。你可以设置你所拥有的值。只有合适的位才会被设置。

你试过吗?