我正在维护一个旧的代码库,即使用整数类型与位字段结构的联合进行类型双关。我的编译器是VS2017。例如,代码类似于以下内容:
struct FlagsType
{
unsigned flag0 : 1;
unsigned flag1 : 1;
unsigned flag2 : 1;
};
union FlagsTypeUnion
{
unsigned flagsAsInt;
FlagsType flags;
};
bool isBitSet(unsigned flagNum, FlagsTypeUnion flags)
{
return ((1u << flagNum) & flags.flagsAsInt);
}此代码存在许多未定义的行为问题。也就是说,类型双关是否是定义的行为引起了激烈的争论,但最重要的是,打包位字段的实现是实现定义的。为了解决这些问题,我想添加静态断言语句来验证VS实现是否允许使用这种方法。但是,当我试图添加以下代码时,我会得到错误的C2131:常量。
union FlagsTypeUnion
{
unsigned flagsAsInt;
FlagsType flags;
constexpr FlagsTypeUnion(unsigned const f = 0) : flagsAsInt{ f } {}
};
static_assert(FlagsTypeUnion{ 1 }.flags.flag0,
"The code currently assumes bit-fields are packed from LSB to MSB");是否有任何方法添加编译时检查来验证类型双关和位打包代码的工作方式与运行时代码假设的相同?不幸的是,这段代码分散在整个代码库中,因此更改结构是不可行的。
发布于 2022-04-06 16:03:58
您可以使用std::bit_cast (C++20):
struct FlagsType
{
unsigned flag0 : 1;
unsigned flag1 : 1;
unsigned flag2 : 1;
unsigned padding : 32 - 3; // Needed for gcc
};
static_assert(std::is_trivially_constructible_v<FlagsType>);
constexpr FlagsType makeFlagsType(bool flag0, bool flag1, bool flag2)
{
FlagsType res{};
res.flag0 = flag0;
res.flag1 = flag1;
res.flag2 = flag2;
return res;
}
static_assert(std::bit_cast<unsigned>(makeFlagsType(true, false, false)) == 1);constexpr检查的填充位。https://stackoverflow.com/questions/71768987
复制相似问题