Jazcash
Jazcash

Reputation: 3312

Storing 8 logical true/false values inside 1 byte?

I'm working on a microcontroller with only 2KB of SRAM and desperately need to conserve some memory. Trying to work out how I can put 8 0/1 values into a single byte using a bitfield but can't quite work it out.

struct Bits
{
    int8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
};

int main(){
    Bits b;
    b.b0 = 0;
    b.b1 = 1;

    cout << (int)b.b0; // outputs 0, correct
    cout << (int)b.b1; // outputs -1, should be outputting 1
}

What gives?

Upvotes: 65

Views: 5041

Answers (4)

Luciano
Luciano

Reputation: 3009

Signed and unsigned integers are the answer.

Keep in mind that signaling is just an interpretation of bits, -1 or 1 is just the 'print' serializer interpreting the "variable type", as it was "revealed" to cout functions (look operator overloading) by compiler, the bit is the same, its value also (on/off) - since you have only 1 bit.

Don't care about that, but is a good practice to be explicit, so prefer to declare your variable with unsigned, it instructs the compiler to mount a proper code when you set or get the value to a serializer like "print" (cout).

"COUT" OPERATOR OVERLOADING: "cout" works through a series of functions which the parameter overloading instructs the compiler which function to call. So, there are two functions, one receives an unsigned and another signed, thus they can interpret the same data differently, and you can change it, instructing the compiler to call another one using cast. See cout << myclass

Upvotes: 0

dtech
dtech

Reputation: 49329

As a word of caution - the standard doesn't really enforce an implementation scheme for bitfields. There is no guarantee that Bits will be 1 byte, and hypothetically it is entirely possible for it to be larger.

In practice however the actual implementations usually follow the obvious logic and it will "almost always" be 1 byte in size, but again, there is no requirement that it is guaranteed. Just in case you want to be sure, you could do it manually.

BTW -1 is still true but it -1 != true

Upvotes: 14

Potatoswatter
Potatoswatter

Reputation: 137940

As noted, these variables consist of only a sign bit, so the only available values are 0 and -1.

A more appropriate type for these bitfields would be bool. C++14 §9.6/4:

If the value true or false is stored into a bit-field of type bool of any size (including a one bit bit-field), the original bool value and the value of the bit-field shall compare equal.

Yes, std::uint8_t will do the job, but you might as well use the best fit. You won't need things like the cast for std::cout << (int)b.b0;.

Upvotes: 3

Carl Norum
Carl Norum

Reputation: 225252

All of your bitfield members are signed 1-bit integers. On a two's complement system, that means they can represent only either 0 or -1. Use uint8_t if you want 0 and 1:

struct Bits
{
    uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
};

Upvotes: 112

Related Questions