Determining a specific value from binary given a byte - c

I can determine a hexadecimal value per given byte by doing:
hex = char & 0xff;
For example, my hex value is 50. This, in binary, would be 0011 0010.
I am looking at 2^5 and 2^4 binary place, which value in my example above is 11. Since this will be consistent regardless of hex value, how would I set my binary value to be equal to 11 (or to the 2^5 and 2^4 binary place)?

The trick here is to mask and shift: first, create a binary "mask" that has ones in the positions that you want to keep; in your example, the mask would be 0x30. Then apply binary "and" to the original number and the mask, and shift the result by the position of the smaller bit position (in this case, that's 4):
hex4and5 = (ch & 0x30) >> 4;
You can reverse the masking and shifting if it makes things easier for you:
hex4and5 = (ch >> 4) & 0x03; // Note that the mask is shifted, too
To make a mask from a list of bit positions, use binary "or" on expressions of 1 << pos, where pos is the binary position of interest. For example, to build the mask for positions 4 and 5 use
int mask4and5 = (1 << 4) | (1 << 5);

Related

How to set masked bits to a specified number?

I haven't been able to find an answer to this on Google, nor do I have any better search ideas. If I have a 2 byte number, a mask, and a third number, how do I replace the masked bits with the third number. For example if I have 0xABCD, the mask 0x0F00, and third number 4 - I would like to replace B with 4 to get A4CD. In other words, I want to be able to replace arbitrary bits selected by a mask with the bits of another arbitrary number (we are assuming that the number replacing the bits fits - i.e. if I mask 5 bits, the number to replace those 5 bits requires 5 bits or less to represent.)
The goal is to replace the bits of number selected by mask with those of value, shifted appropriately, assuming value does not exceed the target range.
Masking off the target bits is easy: number &= ~mask; achieves that simply.
The tricky part is to shift value to the left by the number of zero bits in mask below the set ones. You can write a loop for this.
Here is a simple implementation:
unsigned set_bits(unsigned number, unsigned mask, unsigned value) {
// assuming mask != 0
number &= ~mask;
while (!(mask & 1)) {
value <<= 1;
mask >>= 1;
}
return number | value;
}
You can compute the shift value as a multiplier this way: subtracting one from the mask sets all its 0 low bits to 1, or-ing this value with mask sets all low bits to 1 and xor-ing with mask yields a mask with just the low bits set. Adding 1 to this mask gives the power of 2 by which to multiply value to shift it in place. This works also if there are no 0 bits in the low order bits of mask.
As commented by aschepler, (A ^ (A | B)) == (~A & B) so the expression ((mask ^ (mask | (mask - 1))) + 1) can be simplified as (((mask - 1) & ~mask) + 1).
An elegant simplification was provided by Falk Hüffner: (((mask - 1) & ~mask) + 1) is just mask & -mask.
Here is a branchless version using this trick:
unsigned set_bits(unsigned number, unsigned mask, unsigned value) {
return (number & ~mask) | (value * (mask & -mask));
}
Making this an inline function may help the compiler generate optimal code for constant mask values.

How does this bits reversion in a byte work?

I'm new to programming and I found this method to reverse bits in a byte in C:
//(10000011) -> (11000001)
unsigned char reverse(unsigned char b) {
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b;
}
posted by an user in answer to this question, but I can't understand how it works. What do these constants mean?
It might help to look at the binary representation of the above numbers:
0xF0: 11110000
0x0F: 00001111
0xCC: 11001100
0x33: 00110011
0xAA: 10101010
0x55: 01010101
The first pair of numbers are used to mask out and swap the first 4 bits and the last 4 bits of a byte.
The second pair masks out and swaps the first 2 bits and last 2 bits of a set of 4 bits.
The third pair masks out and swap adjacent pairs of bits.
The code first swaps the "nibbles", i.e. most significant 4 bits with least significant 4 bits. Then it swaps two top order pairs together, and bottom pairs together; finally it does pairwise swaps of 2n and 2n+1 bits.
I am going to denote the bits of the original value of b here by their exponent, in angle brackets (this is just a pseudo notation that I am using here, not correct C); I use o to mark any bit that is 0 always. So in the beginning we have
<76543210>
No in the first operation we have
<76543210> & 0xF0 -> <7654oooo>
<76543210> & 0x0F -> <oooo3210>
Now the former is shifted right by 4 bits, and the latter left by 4, thus we get
<7654oooo> >> 4 -> <oooo7654>
<oooo3210> << 4 -> <3210oooo>
Finally these are or'ed together, and thus after the statement
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
the value of b is the permutation <32107654> of the original bits.
In the second statement the mask 0xCC is 11001100 in binary, and 0x33 is 00110011 in binary; the intermediate values are:
(<32107654> & 0xCC) >> 2 -> <32oo76oo> >> 2 -> <oo32oo76>; and
(<32107654> & 0x33) << 2 -> <oo10oo54> << 2 -> <10oo54oo>.
These 2 or'ed together will result in permutation <10325476>. Now finally, the mask 0xAA is 10101010 in binary, and 0x55 is 01010101. Thus we have
(<10325476> & 0xAA) >> 1 -> <1o3o5o7o> >> 1 -> <o1o3o5o7>; and
(<10325476> & 0x55) << 1 -> <o0o2o4o6> << 1 -> <0o2o4o6o>
These or'ed together will result in permutation <01234567> which is the reverse of the original.
So it's just a lot of bit shifting. The bits are in the following order:
76543210
Now, first line, first part keeps high bits, sets lower bits to 0 (mask is 0b11110000), shifts them 4 to the right. Second part does the same for the lower bits (mask is 0b00001111), and shifts to the left:
first line, first part: 7654xxxx => xxxx7654 (bits shift to the right)
first line, second part: xxxx3210 => 3210xxxx (bits shift to the left)
add them together: => 32107654
Then, second line. Same action, different masks (0b11001100 and 0b00110011, respectively), with 32107654:
second line, first part: 32xx76xx => xx32xx76 (bits shift to the right)
second line, second part: xx10xx54 => 10xx54xx (bits shift to the left)
add them together: => 10325476
Third line is the same with a again other masks(0b10101010 and 0b01010101, respectively), with 10325476:
third line, first part: 1x3x5x7x => x1x3x5x7 (bits shift to the right)
third line, second part: x0x2x4x6 => 0x2x4x6x (bits shift to the left)
add them together: => 01234567
So we end up, finally, with the action:
76543210 => 01234567
Let's number the bits in b as follows:
01234567
0xF0 in binary is 11110000, and 0x0F is 00001111. The first assignment shifts the leftmost 4 bits to the right, and the rightmost 4 bits to the left, then combines them with OR, so the result is:
45670123
0xCC is 11001100, and 0x33 is 00110011. When these masked bits are shifted by 2 bits and combined, the result is:
67452301
Finally, 0xAA is 10101010 and 0x55 is 01010101. When these masks and shifts are done, the result is:
76543210
Voila! this is the reversed order.
Notice that for each pair of shifts, the bit masks are inverses of each other, and the number of bits being shifted are the same as the length of the sequences of 1 bits in the mask. So each of them is swapping groups of bits whose size is that sequence length.
You need to understand 4 main things in order to understand what above code means.
& (AND) Bitwise Operator.
| (OR) Bitwise Operator.
>> (Right Shift Operator).
<< (Left Shift Operator).
Luckily, I just have written a detailed blog that explains everything about Number System and Bit Manipulation

C expression that sets the last n bits of int variable to zero

In other words, sets the last 5 bits of integer variable x to zero, also it must be in a portable form.
I was trying to do it with the << operator but that only moves the bits to the left, rather than changing the last 5 bits to zero.
11001011 should be changed to 11000000
Create a mask that blanks out that last n integers if it is bitwise-ANDed with your int:
x &= ~ ((1 << n) - 1);
The expression 1 << n shifts 1 by n places and is effectively two to the power of n. So for 5, you get 32 or 0x00000020. Subtract one and you get a number that as the n lowest bits set, in your case 0x0000001F. Negate the bits with ~ and you get 0xFFFFFFE0, the mask others have posted, too. A bitwise AND with your integer will keep only the bits that the mask and your number have in common, which can only bet bits from the sixth bit on.
For 32-bit integers, you should be able to mask off those bits using the & (bitwise and) operator.
x & 0xFFFFFFE0.
http://en.wikipedia.org/wiki/Bitwise_operation#AND
You can use bitwise and & for this
int x = 0x00cb;
x = x & 0xffe0;
This keeps the higher bits and sets the lower bits to zero.

Understanding shifting and logical operations

I am trying to read the 'size' of an SD card. The sample example which I am having has following lines of code:
unsigned char xdata *pchar; // Pointer to external mem space for FLASH Read function;
pchar += 9; // Size indicator is in the 9th byte of CSD (Card specific data) register;
// Extract size indicator bits;
size = (unsigned int)((((*pchar) & 0x03) << 1) | (((*(pchar+1)) & 0x80) >> 7));
I am not able to understand what is actually being done in the above line where indicator bit is being extracted. Can somebody help me in understanding this?
The size is made up of bits from two bytes. One byte is at pchar, the other at pchar + 1.
(*pchar) & 0x03) takes the 2 least significant bits (chopping of the 6 most significant ones).
This result is shifted one bit to the left using << 1. For example:
11011010 (& 0x03/00000011)==> 00000010 (<< 1)==> 00000100 (-----10-)
Something similar is done with pchar + 1. For example:
11110110 (& 0x80/10000000)==> 10000000 (>> 7)==> 00000001 (-------1)
Then these two values are OR-ed together with |. So in this example you'd get:
00000100 | 00000001 = 00000101 (-----101)
But note that the 5 most significant bits will always be 0 (above indicated with -) because they were &-ed away:
To summarize, the first byte holds two bits of size, while the second byte only one bit.
It seems the size indicator, say SI, consists of 3 bits, where *pchar contains the two most significant bits of SI in its lowest two bits (0x03) and *(pchar+1) contains the least significant bit of SI in its highest bit (0x80).
The first and second line figure out how to point to the data that you want.
Let's now go through the steps involved, from left to right.
The first portion of the operations takes the byte pointed to by pchar, performs a logical AND on the byte and 0x03 and shifts over that result by one bit.
That result is then logically ORed with the next byte (*pchar+1), which in turn is ANDed with 0x80, which is then right shifted by seven bits. Essentially, this portion just strips off the first bit in the byte and shifts it over by seven bits.
What the result is essentially this:
Imagine pchar points to the byte where bits are represented by letters: ABCDEFGH.
The first part ANDs with 0x03, so we are left with 000000GH. This is then left shifted by one bit, so we are left with 00000GH0.
Same thing for the right portion. pchar+1 is represented by IJKLMNOP. With the first logical AND, we are left with I0000000. This is then right shifted seven times. So we have 0000000I. This is combined with the left hand portion using the OR, so we have 00000GHI, which is then casted into an int, which holds your size.
Basically, there are three bits that hold the size, but they are not byte aligned. As a result, some manipulation is necessary.
size = (unsigned int)((((*pchar) & 0x03) << 1) | (((*(pchar+1)) & 0x80) >> 7));
Can somebody help me in understanding this?
We have byte *pchar and byte *(pchar+1). Each byte consists of 8 bits.
Let's index each bit of *pchar in bold: 76543210 and each bit of *(pchar+1) in italic: 76543210.
1.. ((*pchar) & 0x03) << 1 means "zero all bits of *pchar except bits 0 and 1, then shift result to the left by 1 bit":
76543210 --> xxxxxx10 --> xxxxx10x
2.. (((*(pchar+1)) & 0x80) >> 7) means "zero all bits of *(pchar+1) except bit 7, then shift result to the right by 7 bits":
76543210 --> 7xxxxxxx --> xxxxxxx7
3.. ((((*pchar) & 0x03) << 1) | (((*(pchar+1)) & 0x80) >> 7)) means "combine all non-zero bits of left and right operands into one byte":
xxxxx10x | xxxxxxx7 --> xxxxx107
So, in the result we have two low bits from *pchar and one high bit from *(pchar+1).

How do I get the lower 8 bits of an int?

Lets say I have an int variable n = 8. On most machines this will be a 32 bit value. How can I only get the lower 8 bits (lowest byte) of this in binary? Also how can I access each bit to find out what it is?
unsigned n = 8;
unsigned low8bits = n & 0xFF;
Note a few things:
For bitwise operations, always use the unsigned types
Bits can be extracted from numbers using binary masking with the & operator
To access the low 8 bits the mask is 0xFF because in binary it has its low 8 bits turned on and the rest 0
The low 8 bits of the number 8 are... 8 (think about it for a moment)
To access a certain bit of a number, say the kth bit:
unsigned n = ...;
unsigned kthbit = (1 << k) & n;
Now, kthbit will be 0 if the kth bit of n is 0, and some positive number (2**k) if the kth bit of n is 1.
Use bitwise arithmetic to mask off the lowest 8 bits:
unsigned char c = (x & 0xFF);
To access the nth lowest bit, the equation is (x & (1 << n)) (n of zero indicates the least significant bit). A result of zero indicates the bit is clear, and non-zero indicates the bit is set.
The best way is to use the bit logical operator & with the proper value.
So for the lower 8 bits:
n & 0xFF; /* 0xFF == all the lower 8 bits set */
Or as a general rule:
n & ((1<<8)-1) /* generate 0x100 then subtract 1, thus 0xFF */
You can combine with the bit shift operator to get a specific bit:
(n & (1<<3))>>3;
/* will give the value of the 3rd bit - note the >>3 is just to make the value either 0, or 1, not 0 or non-0 */
You can test if a particular bit is set in a number using << and &, ie:
if (num & (1<<3)) ...
will test if the fourth bit is set or not.
Similarly, you can extract just the lowest 8 bits (as an integer) by using & with a number which only has the lowest 8 bits set, ie num & 255 or num & 0xFF (in hexadecimal).

Resources