Click here to Skip to main content
15,884,013 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Setting or clearing a given bit i in a byte B is straightforward (and often documented), using shift and bitwise operations:
C++
B|= 1 << i;  // 1 shift, 1 or
B&= ~(1 << i); // 1 shift, 1 complement, 1 and

But copying the value of a one bit variable b (instead of the constant 0 or 1) is not so often mentioned. Here is a solution I can think of:
C++
B= (B & ~(1 << i)) | (b << i); // 2 shifts, 1 complement, 1 and, 1 or

Is it possible to do that in less operations (branches not allowed, of course) ?
Posted
Updated 5-Aug-13 23:10pm
v2

1 solution

A good source for such problems is Bit Twiddling Hacks[^]. See 'Conditionally set or clear bits without branching' for your task. Adding an instruction to generate the mask, this can be used:
C++
unsigned m = 1U << i;
B ^= (-b ^ B) & m;
// or
B = (B & ~m) | (-b & m);
 
Share this answer
 
Comments
YvesDaoust 6-Aug-13 6:22am    
Nice try. The expressions are indeed correct. I'll remember the -b trick!

Unfortunately in my context I cannot precompute the mask m (and even less its complement), so that the operation count is not reduced.
Jochen Arndt 6-Aug-13 6:35am    
Looking again over my solution I recognized that you can omit the mask generation line when using the first solution:
B ^= (-b ^ B) & (1U << i);
Still 5 operations. But I think that it can't be solved with less operations.
YvesDaoust 6-Aug-13 6:52am    
Yep, seems difficult to lower to 4 operations. Given the small domain, it is thinkable to fully tabulate the function (2^8 * 8 * 2 entries = 4 kB), but even the table lookup has a cost...
nv3 6-Aug-13 8:26am    
My 5 for the interesting link, Jochen. But it seems that there is no better way than the one OP has proposed in his question. I would go for the straight forward implementation suggested by OP, even if the -b variant might save a cycle or two. It is much easier to read and hence maintain.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900