Reputation: 9245
I found some code online that performs this task:
byte = byte >> field;
byte = byte & 0x01;
return(byte);
However, I don't understand why we can't just do this:
return(byte & field);
Will this work? Why or why not? Are there better implementations?
Upvotes: 3
Views: 2585
Reputation: 1
This can be given by a structure. Lets say:
struct POWERTRAIN_ERROR
{
uint8 ERROR_CODE;
unit8 LAMP_STATUS : 1;
};
struct POWERTRAIN_ERROR pt_error;
uint8 func ( struct POWERTRAIN_ERROR pt)
{
// do something with pt.ERROR_CODE (which is a byte) and pt.LAMP_STATUS which is a bit field
// lets say, this function needs to return the status of 0th bit of ERROR_CODE
return ( pt.ERROR_CODE & 0x1) ;
}
Upvotes: -1
Reputation: 61950
field
represents the bit number of the word you have from the right hand side (LSB). byte = byte >> field
will bring the bit number field
of the byte byte
at the LSB position. Then byte = byte & 0x01
ands the byte with 0x01
that means the result will contain a 1
in the LSB if it had the bit set in the bit number field
originally, or will contain a 0
if it had the bit cleared at that position.
For example the test needed to check if the byte 0x52
has its bit number 4
set or not is shown below.
byte = 0x52 = 0 1 0 1 0 0 1 0
field = 0x04 = 0 0 0 0 0 1 0 0
Operation: byte = byte >> field
The bit number 4 is single quoted below. Note how it moves
intermediate byte | lost bits during
states | right shifting
byte = 0x52 = 0 1 0 '1' 0 0 1 0 |
shift 1 = 0x29 = 0 0 1 0 '1' 0 0 1 | 0
shift 2 = 0x14 = 0 0 0 1 0 '1' 0 0 | 1 0
shift 3 = 0x0A = 0 0 0 0 1 0 '1' 0 | 0 1 0
shift 4 = 0x05 = 0 0 0 0 0 1 0 '1' | 0 0 1 0
Note that the bit 4 is now moved at the LSB/righ most position of the byte
now if we test the rightmost position of the above byte then we can check
if the bit number 4 had its bit set or cleared, with the following operation
Operation: byte = byte & 0x01
byte is now 0x05
byte = 0x05 = 0 0 0 0 0 1 0 '1'
AND & & & & & & & &
0x01 = 0 0 0 0 0 0 0 1
---- ----------------
0x01 0 0 0 0 0 0 0 1
Now byte contains 0x01 so bit number 4 had the bit set. In the other case the
final answer would be 0.
But we cannot do byte & field
to check if the bit which is numbered field
is set or cleared. This is because field
is simply a binary and not a mask. If we did byte & field
then the following would happen.
byte = 0x52 = 0 1 0 1 0 0 1 0
AND & & & & & & & &
field = 0x04 = 0 0 0 0 0 1 0 0
---- ---------------
0x00 0 0 0 0 0 0 0 0
The field
has the value 0x04
which is, its bit number 2
set. With this operation we have checked actually if the bit number 2
is set. If the value of field
was 5
then bit 0
, and 2
would be set, so ANDing directly like above would result if extraction of the state of bit 0
and 2
in the value of byte
, which can take four possible combination.
Other ways to test the bit value of a byte
is instead of shifting the byte
itself, we shift the 0x01
mask field
times to the left, and AND it with the byte, and check if is zero or not. (byte & (0x01 << field)) != 0
will be true when the field
numbered bit is set or false otherwise.
Operation: (0x01 << field)
Shifting 0x01 to the left field times field = 0x04 for the example
= 0x01 = 0 0 0 0 0 0 0 1
shift 1 = 0x02 = 0 0 0 0 0 0 1 0
shift 2 = 0x04 = 0 0 0 0 0 1 0 0
shift 3 = 0x08 = 0 0 0 0 1 0 0 0
shift 4 = 0x10 = 0 0 0 1 0 0 0 0
After the left shift the '1' moves in the bit position 4
Now we AND this with the byte to check if the bit position 4
is set or clear.
byte = 0x52 = 0 1 0 1 0 0 1 0
AND & & & & & & & &
(0x01 << field) = 0x10 = 0 0 0 1 0 0 0 0
---- ---------------
0x10 0 0 0 1 0 0 0 0
Therefore the answer (0x01 != 0) is 1 there fore the bit 4 is set. It the bit 4
was not set then the answer would be 0.
If you have a byte with certain format which you need to test regularly, for example some bitfield of some pre defined word, where each bit means some specific thing then you can keep precomputer mask, which has a one only in the specific bit position which will be tested with that mask. For example to check for one byte the precomputer masks would be:
#define BIT_0 0x01 //(00000001)
#define BIT_1 0x02 //(00000010)
#define BIT_2 0x04 //(00000100)
#define BIT_3 0x08 //(00001000)
#define BIT_4 0x10 //(00010000)
#define BIT_5 0x20 //(00100000)
#define BIT_6 0x40 //(01000000)
#define BIT_7 0x80 //(10000000)
So to test the bit 4 in byte
we have to do return (byte & BIT_4)
or return (byte & BIT_4) != 0;
Depending on what the bit position represents the name of the macro could be set.
Upvotes: 1
Reputation: 43558
The first one is equivalent to:
return (byte >> field) & 0x01;
What it really does is shift to the bit with position field
and return 1
if that bit is set, 0
otherwise.
The one you propose is incorrect because it doesn't shift to the offset of the designated field. For example, byte & 5
doesn't make any sense.
The function can as well be written like this:
return byte & (1 << field);
Of course, if you intend to pass 1 << 5
to it instead of 5
, you can write it your way.
I suppose field
is a number that indicates the position of the bit we are interested in, so for a single byte it would be in the range 0..7
.
Upvotes: 3
Reputation: 51
The 1st example moves the required bit into the LSB of the return but the second example simply masks out all the bits that are not required.
Upvotes: 0
Reputation: 33126
If you really want the return value to be zero or one you can either
return ((byte & (1 << field)) != 0);
or
return ((byte >> field) & 0x01);
Both forms simplify a bit if all you care about is that the return value is zero or non-zero.
Upvotes: 1
Reputation: 22693
In the first code sample, field is the position of the bit in the field of which you want the value.
In the second sample, field would have to be an int with that bit set to one, i.e. 1 << field
.
Upvotes: 1