Reputation: 812
I'm trying to write a macro in C that gets a byte (char) and an index, then it reads the index
th bit from that byte.
This is what I got:
#define READBIT(byte, index) (byte) & (1 << (index))
And this is how I check it:
for (i = 7; i >= 0; i--)
{
printf("%d", READBIT('a', i));
}
It prints 0643200001
.
Why isn't it working and how do I fix it?
Upvotes: 1
Views: 1172
Reputation: 11
This question was asked some time ago and I see from the comments that someone deleted their answer which may have addressed the 'why isn't it working' part of the OPs question. I'll add my 2 cents
It is working, just not how you expected it to and it boils down to the usage of the shift operator. 'a' has a decimal value of 97 or '0110 0001' in binary. Your macro
#define READBIT(byte, index) (byte) & (1 << (index))
takes the 1 and shifts it left some number (7 to 0) and does a unary and against the binary of 'a', so for example:
if index = 7 then '0110 0001' & '1000 000' which is '0000 0000' or 0
if index = 6 then '0110 0001' & '0100 000' which is '0100 0000' or 64
if index = 5 then '0110 0001' & '0010 000' which is '0010 0000' or 32
and so forth, and indeed this is what your output shows. To produce the 1's and 0's as is expected and as has been correctly pointed out in the other answer, you really want to shift the byte right some number (7 to 0) and do the unary operation against 1 like so
#define READBIT(byte, index) (((byte) >> (index)) & 1)
then we would get
v------>v
if index = 7 then '0110 0001' shifted right 7 becomes '0000 0000'
and '0000 0000' & '0000 0001' is '0000 0000' or 0
v----->v
if index = 6 then '0110 0001' shifted right 6 becomes '0000 0001'
and '0000 0001' & '0000 0001' is '0000 0001' or 1
v---->v
if index = 5 then '0110 0001' shifted right 5 becomes '0000 0011'
and '0000 0011' & '0000 0001' is '0000 0001' or 1
and so forth.
Alternatively, the original macro could be fixed by adding a '!= 0' to the result which would then return true (1) or false (0). The original macro would then look like
#define READBIT(byte, index) ((byte) & (1 << (index)) != 0)
Hopefully this will be helpful to somebody in the future.
Upvotes: 1
Reputation:
#define READBIT(byte, index) (((unsigned)(byte) >> (index)) & 1)
Noting that >>
and <<
are better defined for unsigned values.
Upvotes: 5