0

I wrote the following and I expected that 16 would be printed.

#include <iostream>

enum E : long { e = 16 };

struct X 
{
    E e : 5;
};

X x;


int main(){ x.e = E::e; std::cout << static_cast<int>(x.e) << std::endl; }

DEMO

But it wasn't. I got a compiler warning and -16 was printed instead. The warning was:

warning: implicit truncation from 'E' to bitfield changes value from 16 to -16 

It's unclear to me. Why was the warning display and why was -16 printed? I declared the bit-field of size of 5 that's enough to store 16 in there.

2
  • 2
    5 bits is not enough to hold 16 if the type is signed. Change the enum's underlying type to unsigned and your code should work. Commented Dec 19, 2014 at 6:32
  • 1
    I think you want unsigned long ... coliru.stacked-crooked.com/a/6a1576333fd7ec55 Commented Dec 19, 2014 at 6:47

1 Answer 1

1

It is a two's complement issue with signed values. You're going out of range of what a 5-bit signed value can represent.

If you only have 5 bits to store the value of 16, you'll have 10000. The leading 1 indicates that this is a negative value. Only 4 bits represent the magnitude when you have 5 bits for a signed value. To determine the absolute value of a 2s complement value, you flip all the bits and add 1, so

10000 -> 01111 -> 10000 which is 16, so it's negative 16.

Your options would be to use 6 bits instead of 5 if you want to represent the signed range of values, or use an unsigned long in which case you can use all 5 bits for the magnitude

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for your response, but as far as I know it's implementation defined if either two's complement or signed magnitude is used. Right?
More precisely this International Standard permits 2’s complement, 1’s complement and signed magnitude representations for integral types. from 3.9.1/8
if you use long then it's a signed value. C++ doesn't require that signed values be implemented as two's complement, but you are out of the range of values that can be represented by this value. If you use unsigned long it will be an unsigned value.
You're getting -16 because you're using two's complement. signed integer overflow is undefined by the standard so you could get 0 for all you know, the compiler knows what's going on though and is telling you what it's actually doing to cope
because you're using two's complement Why that? C++ doesn't require that signed values be implemented as two's complement I haven't come across the requirements, couldn't you get the reference?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.