c++ packed array of bool

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I currently have an array

unsigned char status[8]

which I used to maintain a boolean status of some system resources.

clearly this is wasteful of RAM.

I know that I can use macros and manipulate individual bits but was wondering if there was a built-in capability to handle this sort of operation that i was overlooking.

bool status[8]

uses 8 bytes.

I even thought of using a class with the [] operator overloaded but concluded that this wouldn't work as it would not be possible to return a reference to a bit field rather than a byte.

before I implement the macro and bit masks I thought I would check with the forum to see if there was a "didn't you know" type response.

regards
Greg

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's my approach:

// bitvector.h - Simple support for bit-masks
//
// This file defines a datatype that can be useful for setting/testing
// individual bits in large (multibyte) collections of bits
//
#ifndef BITVECTOR_H
#define BITVECTOR_H
#include 

struct BitSpec
{
    uint8_t mask;
    uint8_t byteOffset;

};

// Sometimes you feel like having both a "which byte in list"
// value as well as a which "bit set in byte" mask
//
extern BitSpec bitSpecOf(uint8_t bitNumber);


// Sometimes you don't
//
extern uint8_t bitMaskFor(uint8_t bitNumber);

#endif
// bitvector.cpp - A fancy way to get bitmasks made
//
#include "bitvector.h"
#include "forceFlash.h"
#include 

static uint8_t bitWeights[] FORCEFLASH = { 1, 2, 4, 8, 16, 32, 64, 128 };

uint8_t bitMaskFor(uint8_t bitNumber)
{
    bitNumber &= 7; 
    uint8_t answer = pgm_read_byte(bitWeights + bitNumber);
    return answer;
}


BitSpec bitSpecOf(uint8_t bitNumber)
{
    BitSpec answer;
    answer.byteOffset = bitNumber / 8;
    answer.mask = bitMaskFor(bitNumber);

    return answer;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why wouldn't you just use bitfields in a struct?

typedef struct {
 uint8_t b0:1;
 uint8_t b1:1;
 uint8_t b2:1;
 uint8_t b3:1;
 uint8_t b4:1;
 uint8_t b5:1;
 uint8_t b6:1;
 uint8_t b7:1;
} bits_t;

bits_t status;

status.b3 = 1;

'status' is one byte that holds 8 variables ('b0'..'b7'). Obviously you could use more meaningful names than b0..b7 though this solution is fairly generic.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Why wouldn't you just use bitfields in a struct?

I would like to be able to say
if available(cardNumber)
{
    ....
}

regards
Greg

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK:

typedef union {
 uint8_t byte;
 bits_t bits;
} joined_t;

joined_t status;

status.bits.b3 = 1;

cardNumber = 3;
if (status.byte & (1 << cardNumber)) {
  ...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

gregd99 wrote:
I even thought of using a class with the [] operator overloaded but concluded that this wouldn't work as it would not be possible to return a reference to a bit field rather than a byte.
Sure you can. It just takes more work:
class BitRef
{
private:
    uint8_t mask;
    uint8_t *toByte;

public:
    BitRef(uint8_t m, uint8_t *tb) : mask(m), toByte(tb) {}

    operator bool() const { return 0 != *toByte & mask); }
    bool operator=(bool rhs) { if(rhs) set(); else clr(); return rhs; }
    void set() { *toByte|=mask; }
    vold clr() { *toByte&=~mask; }
};

template class BitArray {
private:
    uint8_t data[1+(bitsNum-1)/8];

public:
    BitRef operator[](uint8_t j) { BitRef retval(1<<(j & 7), data+j/8); return retval; }
} ;

The real issue is whether its worth any effort.
Do you need those 7 bytes for anything?
If not, why bother?

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As skeeve said, it is perfectly possible to return a "reference" to a packed bit. In most cases, the compiler will do a very good job of optimizing a way unnecessary operations, but it is still likely to take more flash to deal with the accesses than the a standard bool array. And for a savings of only 7 bytes... well, I guess it might be worth it in some applications. If you were looking at 500 boolean variables, on the other hand, some form of packed storage becomes a much bigger win.

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Sure you can. It just takes more work:
Gosh.... it will take me a while to understand that code!

Apart from a couple of typos... it works fine.

Quote:
before I implement the macro and bit masks I thought I would check with the forum to see if there was a "didn't you know" type response.

Thanks to everyone for the discussion and ideas.... I am off to work on the bitmask solution!

regards
Greg