TransWikia.com

Can both bitwise set/resets be achieved in one line with ternary operators?

Stack Overflow Asked by user8585939 on November 29, 2021

I would like to express the following in a more condensed form:

if (a||b) { alarm |= (1UL << 4) }
else { alarm &= ~(1UL << 4) }

However, I am not sure how to do this given the differing bitwise assignments and not just expressions/values. i.e.:

alarm = (a || b) ? (|= (1UL << 4)) : (&= ~(1UL << 4));

Is it possible?

Thanks,

5 Answers

You could do:

alarm = (alarm & ~(1UL << 4)) | ((a || b) ? (1UL << 4) : 0);

This always clears the bit from alarm, then ORs it back in if (a || b) is true.

It seems kinda pointless.

Answered by keithmo on November 29, 2021

Not recommended, but how about, pretending everything is an int and writing m for the bit(s) you want to set clear:

int f = -!(a||b);
  alarm = f ^ ( (f^alarm) | m);

The explanation is: since (a||b) is 0 or 1, f is 0 (if either a or b is true) and -1 otherwise. In the first case the second statement is the same as

alarm = alarm | m

In the second case it is the same as

alarm = ~((~alarm)|m) 

ie

alarm = alarm & ~m

I expect that some -- perhaps quite a lot of -- casting can make this work for the case you have where m and alarm are, I'd guess, unsigned longs.

But if I saw code like this I would spend a while figuring out what it did, curse the author, and change the code to the if else form

Answered by dmuir on November 29, 2021

Can both bitwise set/resets be achieved in one line with ternary operators?

Yes, but it's not a very satisfying reduction:

alarm = (a || b) ? (alarm | (1UL << 4)) : (alarm & ~(1UL << 4));

You cannot avoid repeating alarm in the second and third operands of ?:, because each of those needs to be a complete expression that, when selected, evaluates to the wanted final value. The original value of alarm is an essential input to the computation of its new value either way, so it must appear in both of the last two operands if overall you use a ternary expression.

I find the if-statement version clearer.

Answered by John Bollinger on November 29, 2021

I'd like to focus on the following part of the question:

alarm = (a || b) ? (|= (1UL << 4)) : (&= ~(1UL << 4));

Is it possible?

This is basically the same as replacing:

x = z ? (c + d) : (c * d);

By:

x = c (z ? + : *) d;

This syntax is not possible in C.

I would like to express the following in a more condensed form

There are other possibilities to do this. The other answers contain examples how you can do that.

Answered by Martin Rosenau on November 29, 2021

I think this would work. I wouldn't say it is more readable and it is certainly not going to result in more efficiency:

alarm = (alarm &~ (1UL << 4)) + ((a||b) << 4);

Answered by rici on November 29, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP