问题很简单。鉴于
struct Foo{
bool : 1;
bool : 1;
int bar : sizeof(int) * 8 - 2;
};
如何在没有警告的情况下将bar的所有位设置为1?
显然我可以做auto v = Foo(); v.bar = ~0;
但是GCC给了我这个:
warning: large integer implicitly truncated to unsigned type [-Woverflow]
我尝试了几种方法,但它总是会发出警告......
答案 0 :(得分:2)
请勿使用~0
(始终为完整int
),~v.bar
,这是正确的尺寸,可以像这样组合使用:
v.bar |= ~v.bar; // or,
v.bar ^= ~v.bar;
应该做任何规模的技巧。
不幸的是,由于无法绑定对位域的引用,因此无法很好地将其包装在函数中。您需要在Foo&
上创建一个函数,或使用宏。
PS。我在使用coliru发布之前快速尝试了这一点,并在本地使用GCC(g ++)5.3.1和6.2.0进行了重新检查 - 都没有使用-Wall
发出任何诊断。
PPS。
使用此测试代码,GCC仅为未签名成员生成诊断:
struct Foo {
int i : 2;
unsigned int u : 30;
};
void bar() {
Foo f {0, 0};
f.i ^= ~f.i; // OK
f.u |= ~f.u; /* warning:
large integer implicitly truncated to unsigned type [-Woverflow]
*/
}
因此,虽然我通常也喜欢无符号整数用于位域或按位操作,但g ++在这里使用int
更快乐更安静。
答案 1 :(得分:1)
这适用于无符号类型。请注意,除非您对未定义的行为感到满意,否则应使用无符号类型完成所有的位操作。
...
unsigned int bar : sizeof(int) * 8 - 2;
...
template <typename T, unsigned n>
constexpr T onebits()
{
return 1 | (((1 << (n-2)) - 1) << 1);
}
v.bar = onebits<unsigned, sizeof(int) * 8 - 2>();