Question

It's common to perform a check and set/clear a flag, eg:

if (some_test) {
   flag |= SOME_FLAG;
}
else {
   flag &= ~SOME_FLAG;
}

A convenient way around this I found so far is...

flag = (some_test) ? (flag | SOME_FLAG) : (flag & ~SOME_FLAG);

This could be made into a macro and its OK, but is there some bit-twiddeling magic to avoid referencing flag twice?

(in case multiple instantiations of flag causes overhead).

Example of what I'm looking for (if C could do ternary operations on operators), is...

flag ((some_test) ? (|=) : (&= ~) SOME_FLAG;

The example above is only to describe what I'm looking for, of course it wont work in its current form.

Was it helpful?

Solution

flag |= SOME_FLAG

is an expression, so you can use a macro

#define SET_FLAG(flag, some_test) \
    ((some_test) ? ((flag) |= SOME_FLAG) : ((flag) &= ~SOME_FLAG))

which evaluates flag only once, and when you use it, you need to type flag only once.

SET_FLAG(a->b->c->d, test);

OTHER TIPS

I know you don't want to access flag twice. But you should be sure that is where the cost is. Often, the conditional jump is more expensive. On the last embedded processor I worked on, the fastest code would have looked like this:

 flag &= ~(SOME_FLAG);
 flag |= (some_test!=0) * SOME_FLAG;

If you want to define a macro and have it avoid evaluating the mask twice then you could do it like this:

#define SETT(FLAG, MASK_T, MASK, TEST) \
do {\
  MASK_T mask = (MASK);\
  FLAG &= ~mask;\
  FLAG |= ((TEST) != 0) * mask;\
}\
while(false)

#define SET(FLAG, MASK, TEST) SETT(FLAG, unsigned, MASK, TEST)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top