Reputation: 2387
This is the code I am going to use to take a set of three booleans and convert it into an int for a switch statement:
int bits = 0;
bool a = true, b = false, c = true; // 101 = 5
bits = bits | a << 2;
bits = bits | b << 1;
bits = bits | c;
cout << bits;
I have eight cases based on the combined state of these three booleans. Am I doing this right?
Right, not in the sense of the syntax although if there are any problems there please advise. More right in the sense of "Is this the best way to solve this problem?"
Upvotes: 4
Views: 361
Reputation: 59101
You can always do the conversion explicitly:
bits = bits | (a ? 1 : 0) << 2;
However I believe C/C++ will handle it implicitly, once you're using the bit-shift operator.
You should define constants for each flag, giving a name to the bit you are setting:
const int a_flag = 2;
bits = bits | (a ? 1 : 0) << a_flag;
Edit:
As you can see from the comments on my answer, most C/C++ programmers prefer to learn implicit conversions and operator precedence. Therefore your original code is "most correct".
Edit 2:
Except, you should use the |=
operator:
const int a_flag = 2;
bits |= a << a_flag;
Upvotes: 0
Reputation: 304
You can make some defines to make easy to work with bits
#define BitSet(arg,bit) ((arg) |= (1<<bit))
#define BitClr(arg,bit) ((arg) &= ~(1<<bit))
#define BitFlp(arg,bit) ((arg) ^= (1<<bit))
#define BitTst(arg,bit) ((arg) & (1<<bit))
Then you can use only one char
keys = 0b00000101;
BitSet (keys,1);
This an common way to work in embedded systems.
Upvotes: 0
Reputation: 596
$ cat ttt.c
//example of C solution
#include <stdio.h>
int main() {
union {
unsigned int val;
struct {
unsigned a : 1;
unsigned b : 1;
unsigned c : 1;
//unsigned d : 1;
//e, f, g, h...
} flags;
} bits;
bits.val=0;
bits.flags.a = 1;
bits.flags.c = 1;
printf("val: %d\n",bits.val);
return 0;
}
~$ ./ttt
val: 5
Upvotes: 1
Reputation: 58667
You're doing it right. You could make the code a little more succinct though:
bits |= (a<<2) | (b<<1) | (c<<0);
Just be aware that the Standard doesn't enforce any size constraint on bool
. Pragmatically speaking there shouldn't be a problem with three bits, but the Standard doesn't back you here.
Upvotes: 1
Reputation: 89926
I would do it as:
bits = (bits << 1) | a;
bits = (bits << 1) | b;
bits = (bits << 1) | c;
which would require less maintenance work if you needed to add or to remove a flag.
However, doing this so that you can use it for a switch
sounds like it might be a bad idea. Adding a flag would double the number of states you'd need to handle, and the case
values would be fragile and hard to read.
But if you really must, here's another approach:
enum
{
c_bit_offset,
b_bit_offset,
a_bit_offset
};
unsigned int bits = (a << a_bit_offset)
| (b << b_bit_offset)
| (c << c_bit_offset);
switch (bits)
{
case 0:
/* Do something. */
break;
case (1 << a_bit_offset):
/* Do something. */
break;
case (1 << a_bit_offset) | (1 << b_bit_offset):
/* Do something. */
break;
...
}
By the way, you probably should use unsigned int
instead of int
.
Upvotes: 0