PaeneInsula
PaeneInsula

Reputation: 2100

c bit ops on single vs multiple bits

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

Answers (3)

nos
nos

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

Win32
Win32

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

jman
jman

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

Related Questions