0

I'm trying to understand a snippet of code which is the following:

unsigned char state = portStates[portNumber];
int bitValue = (state >> 7) & 0x1;

It's doing a bitwise AND on the least-significant bit of state, right? If it returns true (ie, that bit is set), then the number is odd. Otherwise, it's even. Am I correct?

Thanks

the_naive
  • 2,936
  • 6
  • 39
  • 68

2 Answers2

5
int bitValue = (state >> 7) & 0x1;

just shifts state by 7 bits. Then it removes all other bits than the first one.

So converts the 7th bit (most significant bit in most systems where unsigned char is 8 bits) of your value to 0 or 1 value. It could be written as a boolean expression (using the idiomatic double negation):

int bitValue = !!(state & 0x80);

but the shifting and masking directly gives the 0 or 1 value without converting to bool.

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • 2
    1 byte is always 8 bits on modern *general-purpose* CPUs. There are lots of [modern stuff where it need not be true](https://stackoverflow.com/questions/44755034/md5-implementation-for-non-byte-addressable-arch). – Antti Haapala -- Слава Україні Apr 18 '18 at 09:14
  • I may delete that last bit, that's overanswering, just to say: "don't do it". I had that 1 byte wasn't always 8 bits but couldn't find that reference. Well, adding & 0x1 doesn't hurt. – Jean-François Fabre Apr 18 '18 at 09:15
  • 1
    well, you could add that generally this is the MSB (not the LSB as OP thought) ;) – Antti Haapala -- Слава Україні Apr 18 '18 at 09:18
  • 1
    Wouldn't `bitvalue = state > 127 ? 1 : 0;` be a lot more readable -- and let the compiler decide how to optimize? – David C. Rankin Apr 18 '18 at 09:43
  • or `!!(state > 127)` :) in that particular case yes. I don't like ternary that yield bools that much :) – Jean-François Fabre Apr 18 '18 at 11:56
  • 1
    @DavidC.Rankin `state > 127 ? 1 : 0` differs in functionality from `(state >> 7) & 0x1` on exceptionally cases when `CHAR_BIT > 8`. – chux - Reinstate Monica Apr 18 '18 at 12:45
  • @chux: oh yes, that's why I had removed my edit on `state >> 7` (without masking). I'm not touching those formulas again. – Jean-François Fabre Apr 18 '18 at 13:21
  • @chux If `CHAR_BIT` was not *defined* as `8`, then `(state >> 7)` and `(state & 0x80)` would no longer work either? No? – David C. Rankin Apr 18 '18 at 17:23
  • @DavidC.Rankin Why not? If `CHAR_BIT == 9`, then `(state >> 7) & 0x1;` would still report bit 7. It would not be the _most significant bit_, yet that was not OP's posted goal. – chux - Reinstate Monica Apr 18 '18 at 17:24
  • @chux If `CHAR_BIT = 9`, the `unsigned char` would have `9` bytes and neither of the tests would fill their intended purposes of testing the MSB (incorrectly written as LSB in the question). – David C. Rankin Apr 18 '18 at 17:27
  • @DavidC.Rankin OP post does not appear to seek the MSB to me. It looks like OP thought (incorrectly) the code was testing for odd/evenness by testing the LSB. IAC, OP title seeks to understand want is happening - well answered [here](https://stackoverflow.com/a/49894808/2410359). – chux - Reinstate Monica Apr 18 '18 at 17:32
  • @chux If that be the case, and he just be wanting bit-7 irrespective of the size of *unsigned char*, then ye be right -- otherwise a change in `CHAR_BIT` would render any fixed-bit number test wrong as well. But `CHAR_BIT != 8` be not sticking with the code... – David C. Rankin Apr 18 '18 at 17:38
1

(state>>7) returns the value generated by shifting the unsigned char "state" by 7 bits, adding leading zeros. Performing the and operation with one now gives the value of seventh bit in state.

That is, bitValue is 1 iff the seventh bit of state (from the right) is 1, or in other words bitValue is 1 iff state >= 128.