Reputation: 2100
I am trying represent a bunch of values in a single char: 6 on/off flags in the first 6 bits, and using the last 2 bits to hold 4 different values. This seems so basic that macros like this must exist somewhere, but I can't find them.
#define HOT 0x00
#define BIG 0x01
#define FAT 0x02
#define HIT 0x03
#define BAT 0x04
#define ZAX 0x05
#define HOW 0x06
#define TWO_BITS nnn // ???
#define CONDITION_0 nnn // bit combo: 00
#define CONDITION_1 nnn // bit combo: 01
#define CONDITION_2 nnn // bit combo: 10
#define CONDITION_3 nnn // bit combo: 11
void bitter(void)
{
unsigned char myBits = 0;
bool nonsense;
if (myBits & BIG) nonsense = true; // BIG flag on
if (!(myBits & BAT)) nonsense = false; // BAT flag off
myBits = myBits | BIG; // turn on BIG bit
myBits = myBits & ~BIG; // turn off BIG bit
if (TWO_BITS == CONDITION_0)
doThis();
else if (TWO_BITS == CONDITION_1_)
doThat();
// ... etc
}
So what is the best way to code what I want to do with those last 2 bits? I haven't been able to do any performance testing because I haven't figured out how to write the code, but I'm assuming this is the fastest way to do these sort of ops.
[btw, this may smell like homework, but I'm just a 54 year old dog trying to learn some new tricks.]
Upvotes: 1
Views: 2992
Reputation: 229058
It sort of depends on whether you need to deal with those 2 bits on its own, as a (decimal) value between 0 and 3, or if you always treat them as the upper 2 bits of a byte.
Here's one way, we just mask out all the other bits, and define the conditions as the value those 2 bits will make as the upper 2 bits in a byte.
#define TWO_BITS(x) ((x) & 0xC0)
#define CONDITION_0 0
#define CONDITION_1 0x40 // bit combo: 01
#define CONDITION_2 0x80 // bit combo: 10
#define CONDITION_3 0xC0 // bit combo: 11
That is, the upper 2 bits of a byte is the binary 1 1 0 0 0 0 0 0 , which is 0xC0 in hex. And the upper 2 bits being 0 1 , i.e. with all the bits in a byte it would be 0 1 0 0 0 0 0 0 , which is 0x40 in hex.
And your test would have to be
if (TWO_BITS(myBits) == CONDITION_0)
The other approach is to extract those upper 2 bits as a 2 bit integer (that is, a value between 0 and 3). That's easy, just shift the bits 6 places to the right.
#define TWO_BITS(x) ((x) >> 6)
#define CONDITION_0 0x0
#define CONDITION_1 0x01 // bit combo: 01
#define CONDITION_2 0x02 // bit combo: 10
#define CONDITION_3 0x03 // bit combo: 11
The usage would be the same when testing one of the conditions.
if (TWO_BITS(myBits) == CONDITION_0)
A last note, it seems your lower 6 bit flags is a bit wrong, consider e.g.
#define HOW 0x06
0x06 is the binary value 0 0 0 0 0 1 1 0 , so that's actually turning on or testing for 2 bits. You likely want to associate 1 bit with 1 flag, which would be this sequence
#define BIG 0x01
#define FAT 0x02
#define HIT 0x04
#define BAT 0x08
#define ZAX 0x10
#define HOW 0x20
This is often written as a bit shift so it's easy to read which bit it is:
#define BIG (1 << 0) //bit zero
#define FAT (1 << 1) //bit 1
#define HIT (1 << 2) //bit 2
#define BAT (1 << 3) //bit 3 , etc.
#define ZAX (1 << 4)
#define HOW (1 << 5)
Upvotes: 1
Reputation: 1149
You just need to apply a bitmask to the last 2 bits (0x03) and switch on the result:
switch (myBits & 0x03) {
case 0: // CONDITION_0
doThis();
break;
case 1: // CONDITION_1
doThat();
break;
case 2: // CONDITION_2
case 3: // CONDITION_3
}
Also, in case you want them as macros for reusing them:
#define CONDITION_0(X) (((X) & 0x03) == 0)
#define CONDITION_1(X) (((X) & 0x03) == 1)
#define CONDITION_2(X) (((X) & 0x03) == 2)
#define CONDITION_3(X) (((X) & 0x03) == 3)
Then you just need to write something like:
if (CONDITION_0(myBits)) {
doThis();
} else if (CONDITION_1(myBits)) {
doThat();
}
Upvotes: 1
Reputation: 11606
I'm not sure I understand what you want, but it sounds like you want to check if two bits are set. In that case, for example, if you want to check if the last two bits are both set, you'd do:
((myBits & 3) == 3)
Upvotes: 1