8

Details

The reference for bit fields at cppreference presents the following example:

#include <iostream>
struct S {
 // three-bit unsigned field,
 // allowed values are 0...7
 unsigned int b : 3;
};
int main()
{
    S s = {7};
    ++s.b; // unsigned overflow (guaranteed wrap-around)
    std::cout << s.b << '\n'; // output: 0
}

Emphasis on the guaranteed wrap-around comment.

However, WG21 CWG Issue 1816 describe some possible issues with unclear specification of bit field values, and [expr.post.incr]/1 in the latest standard draft states:

The value of a postfix ++ expression is the value of its operand. ...

If the operand is a bit-field that cannot represent the incremented value, the resulting value of the bit-field is implementation-defined.

I'm unsure, however, if this applies also for wrap-around of unsigned bit fields.

Question

  • Is overflow of an unsigned bit field guaranteed to wrap-around?
YSC
  • 38,212
  • 9
  • 96
  • 149
dfrib
  • 70,367
  • 12
  • 127
  • 192
  • 3
    The standard seems pretty clear, cppreference not being a normative reference... – Holt Jan 15 '19 at 17:40
  • I also lean towards ”no, it is implementation defined”, but would like to get an experts opinion. I have seen a few answers here on SO that make use of (assumed?) unsigned bit field wrap-around, e.g. for getting the max value of an unsigned bit field (`-1` assignment). I wonder if those techniques are actually using implementation defined behavior. – dfrib Jan 15 '19 at 17:51
  • Note that assignment of `-1` to a bit-field falls in a different category of problem, see http://eel.is/c++draft/expr.ass#6, which is even clearer. These paragraphs have been added in a recent standard, so these questions might be older than the changes in the standard. – Holt Jan 15 '19 at 17:52
  • I see, that could explain it, thanks. – dfrib Jan 15 '19 at 17:53
  • @Holt But was that ever really guaranteed (wrap around) or was that just (possibly illegally) deduced from unsignedness of the BF member? Wondering what else would be meaning full, though. – Aconcagua Jan 15 '19 at 18:18
  • @Aconcagua I don't think it was guaranteed, but the old standard was not clear on this point. – Holt Jan 15 '19 at 18:26

1 Answers1

9

Both [expr.pos]/1 and [expr.ass]/6 agree that integer overflow on a (signed or unsigned) bit-field is implementation defined.

[expr.pos]/1

[...] If the operand is a bit-field that cannot represent the incremented value, the resulting value of the bit-field is implementation-defined.

[expr.ass]/6

When the left operand of an assignment operator is a bit-field that cannot represent the value of the expression, the resulting value of the bit-field is implementation-defined.

I've fixed the cppreference page. Thank you for noticing.

Community
  • 1
  • 1
YSC
  • 38,212
  • 9
  • 96
  • 149