简体   繁体   English

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

[英]How to set all bits of a bitfield member to 1

The question is pretty simple. 问题很简单。 Given 特定

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

How can I set all bits of bar to 1, without a warning? 如何在不发出警告的情况下将bar的所有位设置为1?

Obviously I can do auto v = Foo(); v.bar = ~0; 显然我可以auto v = Foo(); v.bar = ~0; auto v = Foo(); v.bar = ~0; but GCC gives me this: 但海湾合作委员会给我这个:

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

I have tried a couple of ways, but it always renders a warning... 我尝试了几种方法,但是它总是会发出警告。

Don't use ~0 (which is always a full int ), but ~v.bar , which is the right size and can be combined like so: 不要使用~0 (这始终是一个充满int ),但~v.bar ,这是正确的大小,可以组合,像这样:

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

should do the trick, for any size. 无论大小如何,都应该做到这一点。

Unfortunately you can't nicely wrap it in a function since you can't bind references to bitfields. 不幸的是,由于无法将引用绑定到位域,因此无法很好地将其包装在函数中。 You'd either need to make it a function on Foo& , or use a macro. 您需要使其成为Foo&上的函数,或者使用宏。

PS. PS。 I tried this quickly before posting with coliru , and just re-checked locally with GCC (g++) 5.3.1 and 6.2.0 - neither issue any diagnostic with -Wall . 我在使用coliru进行发布之前很快尝试了此操作 ,只是在本地使用GCC(g ++)5.3.1和6.2.0重新进行了检查-均未使用-Wall发出任何诊断信息。

PPS. PPS。

With this test code, GCC produces a diagnostic only for the unsigned member: 使用此测试代码,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]
  */
}

So although I'd also usually prefer unsigned integers for bitfields or for bitwise manipulation, g++ is happier and quieter with int here. 因此,尽管我通常也更喜欢将无符号整数用于位域或按位操作,但g ++在这里使用int更快乐,更安静。

This works for me for unsigned types. 这对我适用于无符号类型。 Note that all bit-fiddling should be done with unsigned types, unless you're OK with undefined behaviour. 请注意,所有位摆弄都应使用无符号类型完成,除非您对未定义的行为感到满意。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM