Below is a code which returns the signed value of the last 6 bits in an 8 bit binary value however I am struggling to understand how the code does this? Any help would be greatly appreciated.
I understand that (b&0x20)
returns the last 6 bits however the ? b
afterwards and hence the subsequent code has me a little confused.
return (b & 0x20) ? b | ~0x3F : b & 0x3F;
CodePudding user response:
This code is probably written for circumstances in which:
b
is anint
or narrower.- Two’s complement is used to represent negative numbers.
The ?
and :
form a conditional operation. Generally, in X ? Y : Z
, X
is tested. If X
is not zero, Y
is evaluated and used as the result of the expression. If X
is zero, Z
is evaluated and used as the result.
So, in (b & 0x20) ? b | ~0x3F : b & 0x3F
, (b & 0x20)
is tested. b & 0x20
isolates from b
the single bit in 0x20
, so this is testing whether the bit in that position is on.
Let’s consider the “off” result first, when b & 0x3F
is used. 0x3F
is an int
value with the low six bits set to 1 and all higher bits set to 0. When this is ANDed with b
, in b & 0x3F
, the result is the low six bits of b
, with all higher bits set to 0. As an int
, this result has the value of the low six bits of b
.
For the “on” result, b | ~0x3F
is used. The ~
operator flips each bit. Since 0x3F
has the low six bits set to 1 and all higher bits set to 0, ~0x3F
has the low six bits set to 0 and all higher bits set to 1. When that is ORed with b
, in b | ~0x3F
, the result is the low six bits of b
with all higher bits set to 1.
What this does is “sign extend” the low six bits of b
: If the bit in position 5 (0x20
) is clear, the result of (b & 0x20) ? b | ~0x3F : b & 0x3F
is the low six bits of b
with all higher bits cleared. If the bit in position 5 is set, the result is the low six bits of b
with all higher bits set. So the effect is the bit in position 5 is copied to all higher bits.
When two’s complement is used, extending the sign bit of narrower type yields the same value in a wider type.
For example, in three-bit two’s complement:
- 011 represents 3.
- 010 represents 2.
- 001 represents 1.
- 000 represents 0.
- 111 represents −1.
- 110 represents −2.
- 101 represents −3.
- 100 represents −4.
When we sign-extend those to 5 bits, we have:
- 00011 represents 3.
- 00010 represents 2.
- 00001 represents 1.
- 00000 represents 0.
- 11111 represents −1.
- 11110 represents −2.
- 11101 represents −3.
- 11100 represents −4.
A five-bit integer has other bit patterns, of course, but those are the ones we get by sign-extending from a three-bit integer.