Cramming two objects in a single byte in C++

Viewed 72
class A
{
   char c; // c represents a value varying from 0 to 2^7-1 (I don't need a bigger range)
   bool b; // b is a boolean value
}

Class A uses 2 bytes. However, as c is never meant to get a value greater than 2^7-1 (as specified in comments), one of the bit of the byte of c could be used to represent the boolean value b. Something like

class A
{
    unsigned char x;   // x represents both a value varying from 0 to 2^7-1 and a boolean value

public:
    A(unsigned char c, bool b)
    {
        assert(c <= 127);
        x = c;
        if (b) x += 128;
    }

    unsigned char getC()
    {
        if (x >= 128) return x - 128; else return x;
    }

    bool getB()
    {
        return x >= 128;
    }
};

Now class A uses a single byte. I suspect what I want to do might be quite usual and there might be a simpler, faster or more standard solution to do just that. Is there a better solution to cram two objects into a single byte?

2 Answers

You can use bitfields to give a specific bit size to a member.

#include  <iostream>

struct A {
    unsigned char c : 7;
    bool b : 1;
};


int main() {
    std::cout << sizeof(A);
}

Demo

If your code absolutely must store these two values in a single 8-bit field, use masks:

struct a {
    unsigned char value;
    unsigned char get_c() const { return value & 0x7F; }
    void set_c(unsigned char c1} {
        value &= 0x80;
        value |= (c1 & 0x7F);
    }
    bool get_b() const { return value & 0x80; }
    void set_b(bool b1) { value &= 0x7F; value |= (b1 ? 0x80 : 0); }
};

Obviously, using a bit-field is simpler, but the details of how bit-fields are laid out depend on the implementation; you have no guarantee that two fields that add up to 8 bits will be stored in a single 8-bit object.

Related