如何将位域成员的所有位设置为 1

How to set all bits of a bitfield member to 1

本文关键字:设置 位域 成员      更新时间:2023-10-16

这个问题很简单。鉴于

struct Foo{
    bool     : 1;
    bool     : 1;
    int bar  : sizeof(int) * 8 - 2;
};

如何在没有警告的情况下将所有柱线位设置为 1?

显然我可以做auto v = Foo(); v.bar = ~0;但 GCC 给了我这个:

warning: large integer implicitly truncated to unsigned type [-Woverflow]

我已经尝试了几种方法,但它总是发出警告......

不要使用 ~0(它始终是一个完整的int(,而是~v.bar ,这是正确的大小,可以像这样组合:

v.bar |= ~v.bar; // or,
v.bar ^= ~v.bar;

应该做这个伎俩,适合任何尺寸。

不幸的是,您无法

很好地将其包装在函数中,因为您无法将引用绑定到位字段。你要么需要让它成为Foo&上的函数,要么使用宏。

附言。在使用 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更快乐、更安静。

这对我无符号类型有用。请注意,所有位摆弄都应该使用无符号类型完成,除非你对未定义的行为感到满意。

...
   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>();