The following code does not work but demonstrates what I want to do
#define TESTINGMACRO 2 | 3
#if TESTINGMACRO & 1 //Should be inactive
#endif
#if TESTINGMACRO & 2 //Should be active
#endif
#if TESTINGMACRO & 3 //Should be active
#endif
Another alternative:
#define TESTINGMACRO 2, 3
#if TESTINGMACRO == 1 //Should be inactive
#endif
#if TESTINGMACRO == 2 //Should be active
#endif
#if TESTINGMACRO == 3 //Should be active
#endif
I know an enum or an array would work too however some preprocessor blocks contains #includes that might not build. Using preprocessor code allows for testing the rest of the file.
I also know I can do the following but this will be a large file so a single central macro would be cleaner:
#define TESTINGMACRO2
#define TESTINGMACRO3
#ifdef TESTINGMACRO1 //Should be inactive
#endif
#ifdef TESTINGMACRO2 //Should be active
#endif
#ifdef TESTINGMACRO3 //Should be active
#endif
Edit: Just FYI in the first scenario all preprocessor blocks are active in practice. So doing 2 | 3 will activate & 1 as well. This is the case for the second code snippet too. This is not what I want, only 2 and 3 should be active when 2|3.
Edit2: I ended up doing:
#define BIT(n) (1<<n)
#define TESTINGMACRO ( BIT(2) | BIT(3) )
#if TESTINGMACRO & BIT(1) //Inactive
#endif
#if TESTINGMACRO & BIT(2) //Active
#endif
#if TESTINGMACRO & BIT(3) //Active
#endif
Format wise this is closest to my original and in my opinion quite readable. Thanks for all the help
CodePudding user response:
You can use bit fields — but then you need to do it properly:
Define the values as distinct powers of two. Instead of 1, 2, 3, …, use 1 << 0, 1 << 1, 1 << 2, … (aka. 1, 2, 4 …).
Fix the operator precedence by adding parentheses. Remember that macros are expanded via textual replacement.
#define TESTINGMACRO ((1 << 1) | (1 << 2))
#if TESTINGMACRO & (1 << 0) //Should be inactive
#endif
#if TESTINGMACRO & (1 << 1) //Should be active
#endif
#if TESTINGMACRO & (1 << 2) //Should be active
#endif
That said, I would generally recommend using separate feature macros instead, the resulting code is more readble.
CodePudding user response:
#define TESTINGMACRO1
#define TESTINGMACRO2
#define TESTINGMACRO3
#ifdef TESTINGMACRO1 //Should be inactive
#endif
#ifdef TESTINGMACRO2 //Should be active
#endif
#ifdef TESTINGMACRO3 //Should be active
#endif
Just do it. There isn't a better way. This really is what everybody expects.
The actual reason your didn't work is really quite simple though.
#define TESTINGMACRO 2 | 3
is not correct because of operator precedence. It should be
#define TESTINGMACRO (2 | 3)
As Konrad Rudolph has pointed out, 3 isn't a single bit and you probably intended 4. Some people recommend (1 << n) to get the bits, but I normally use hex constants. 0x04, 0x08, 0x10 is easy enough to read.
In theory you can only have 15 bits (signed-ness) before you run into trouble, but in practice it will work for 32 bits because you will almost never encounter a 16 bit host compiler anymore.
CodePudding user response:
The main problem with your approach is that you're using values that have common bits set. Each value should correspond to a single bit. Then you can check for that bit. You've also got a precedence problem since &
has higher precedence than |
.
So instead of 1, 2, and 3 for values you want 1, 2, and 4 (or equivalently, 1<<0
, 1<<1
and 1<<2
).
#define TESTINGMACRO ((1<<1) | (1<<2))
#if TESTINGMACRO & (1<<0) //Should be inactive
#endif
#if TESTINGMACRO & (1<<1) //Should be active
#endif
#if TESTINGMACRO & (1<<2) //Should be active
#endif