10

Consider a class with a number of bool attributes

class A
{
  bool a;
  bool b;
  bool c;
  bool d;
  bool e;
  bool f;
};

While each bool object could be represented with a single bit, here each attribute would take a byte (if I am not mistaken). The object would take 6 bytes instead of just 1 byte (6 bits of which would be actually used). The reason being that bits are not addressable, only bytes are.

To condensate the memory a bit, one could use a vector<bool> or a bitset and then access the attributes, by their indices. For example, one could write a get function as

bool A::get_d() {data[3];}

Ideally, I would love being able to directly access the attributes with InstanceOfA.d. Is it possible to do that, while ensuring that all of my 6 bool are being condensed within the same byte?

Remi.b
  • 17,389
  • 28
  • 87
  • 168

2 Answers2

12

You can use bitfields. Works with Repl.it's gcc version 4.6.3.

#include <iostream>

struct Test 
{
  bool a:1;
  bool b:1;
  bool c:1;
  bool d:1;
  bool e:1;
  bool f:1;
  bool g:1;
  bool h:1;
  //bool i:1; //would increase size to 2 bytes.
};

int main()
{
  Test t;
  std::cout << sizeof(t) << std::endl;
  return 0;
}
Phil M
  • 1,619
  • 1
  • 8
  • 10
  • Exactly what I was looking for! Thank you! I'll accept the answer when I can. – Remi.b Dec 13 '18 at 00:15
  • 6
    Another alternative is `std::bitset`. – Eljay Dec 13 '18 at 00:25
  • 4
    Note, however, that the actual layout of those fields is implementation-defined. The language definition does not require them to be packed. Typically they will be, but if it’s important, check it. – Pete Becker Dec 13 '18 at 01:00
0

If you really care about saving space, you should probably use a bitset instead of a bit field.

You can see this answer for a full comparison, but essentially a bit field will have some overhead due to being struct and the compiler may or may not actually pack elements together in order to save space.

Bitsets however are specifically made to optimize space allocation, and also offer some helpful functions specifically for bit twiddling.

A bitset is logically just an array of bits, but packed to save space. You can use it like such:

std::bitset<8> bacon;
bacon.set();    // 11111111
bacon.reset(1); // 11111101 Note: counts index from the right

std::bitset<4> fancy (std::string("1111"));
fancy[1] = 0;      // 1101 Note: counts index from the right
fancy.test(1) == 0 // true
Increasingly Idiotic
  • 5,700
  • 5
  • 35
  • 73