在联合中设置字段位的最佳方法
Best way to set bits of fields in union
假设我有以下
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
在不影响其他位字段的情况下为特定位赋值的最佳方法是什么?
我可以四处移动,然后赋值,然后再次移动,但这意味着一旦有人改变了位字段的顺序,代码就被破坏了....
C++ 编译器将为您管理位。您可以直接设置值。只会设置适当的位。
你尝试了吗?
I can shift around and then assign and then shift again but it means
once someone changes the order of the bit fields, the code is
broken....
不,这并不意味着代码已损坏。您可以根据需要更改位域(在任何 order/you 中可以保留其中一些未设置)
在你的例子中:
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;
}
编辑: 正如@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
这说明了我要表达的观点(即覆盖联合字段)。
我会考虑从您的 struct S
代码中删除 union
,但我可能看不到您要实现的目标的全貌。
假设我有以下
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
在不影响其他位字段的情况下为特定位赋值的最佳方法是什么?
我可以四处移动,然后赋值,然后再次移动,但这意味着一旦有人改变了位字段的顺序,代码就被破坏了....
C++ 编译器将为您管理位。您可以直接设置值。只会设置适当的位。
你尝试了吗?
I can shift around and then assign and then shift again but it means once someone changes the order of the bit fields, the code is broken....
不,这并不意味着代码已损坏。您可以根据需要更改位域(在任何 order/you 中可以保留其中一些未设置)
在你的例子中:
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;
}
编辑: 正如@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
这说明了我要表达的观点(即覆盖联合字段)。
我会考虑从您的 struct S
代码中删除 union
,但我可能看不到您要实现的目标的全貌。