tags:

views:

134

answers:

3
+3  Q: 

Bitfields in C++

I have the following code for self learning:

#include <iostream>
using namespace std;
struct bitfields{
    unsigned field1: 3;
    unsigned field2: 4;
    unsigned int k:  4;
};

int main(){
    bitfields field;
    field.field1=8;
    field.field2=1e7;
    field.k=18;
    cout<<field.k<<endl;
    cout<<field.field1<<endl;
    cout<<field.field2<<endl;
    return 0;
}

I know that unsigned int k:4 means that k is 4 bits wide, or a maximum value of 15, and the result is the following.

2
0
1

For example, filed1 can be from 0 to 7 (included), field2 and k from 0 to 15. Why such a result? Maybe it should be all zero?

+4  A: 

You're overflowing your fields. Let's take k as an example, it's 4 bits wide. It can hold values, as you say, from 0 to 15, in binary representation this is

0  -> 0000
1  -> 0001
2  -> 0010
3  -> 0011
...
14 -> 1110
15 -> 1111

So when you assign 18, having binary representation

18 -> 1 0010 (space added between 4th and 5th bit for clarity)

k can only hold the lower four bits, so

k = 0010 = 2.

The equivalent holds true for the rest of your fields as well.

roe
+1: For clarity.
kbrimington
+2  A: 

You have these results because the assignments overflowed each bitfield.

The variable filed1 is 3 bits, but 8 takes 4 bits to present (1000). The lower three bits are all zero, so filed1 is zero.

For filed2, 17 is represented by 10001, but filed2 is only four bits. The lower four bits represent the value 1.

Finally, for k, 18 is represented by 10010, but k is only four bits. The lower four bits represent the value 2.

I hope that helps clear things up.

kbrimington
hah! on the same second! :)
roe
+1  A: 

In C++ any unsigned type wraps around when you hit its ceiling[1]. When you define a bitfield of 4 bits, then every value you store is wrapped around too. The possible values for a bitfield of size 4 are 0-15. If you store '17', then you wrap to '1', for '18' you go one more to '2'.

Mathematically, the wrapped value is the original value modulo the number of possible values for the destination type:

For the bitfield of size 4 (2**4 possible values):

18 % 16 == 2
17 % 16 == 1

For the bitfield of size 3 (2**3 possible values):

8 % 8 == 0.

[1] This is not true for signed types, where it is undefined what happens then.

Luther Blissett
Why would it be undefined for signed types? int k:4 would hold -8 thru 7, assigning 18 would still yield two, whereas assigning 15 would yield -1. I'm assuming two's complement arithmetic, which is, after all, the most common. Any other arithmetic would still be well defined though, just not the same.
roe
One goal in the development of C++ was to be as much as possible agnostic to the characteristics of the underlying machine. Therefore the standard documents make no assumption about the representation of signed integers or their behaviour: The can be 1-complement numbers and they may *trap* on overflow.
Luther Blissett
This is of course important to know. For example there are still people who write overflow checks like `x+1<x`, not knowing that according to the rules this can be replaces with 'false'
Luther Blissett