Separating the Nybbles in a Byte with Bitwise Operators in C - c

If we have a decimal value: 123
and its binary version: 01111011
How can I get four leftmost and the four rightmost bits from this byte into 2 separate int variables?
I mean:
int a = 7; // 0111 (the first four bits from the left)
int b = 11; // 1011 (the first four bits from the right)
Much appreciated!

int x = 123;
int low = x & 0x0F;
int high = (x & 0xF0) >> 4;
This is called masking and shifting. By ANDing with 0xF (which is binary 00001111) we remove the higher four bits. ANDing with 0xF0 (which is binary 11110000) removes the lower four bits. Then (in the latter case), we shift to the right by 4 bits, in effect, pushing away the lower 4 bits and leaving only what were the upper 4 bits.
As #owlstead says in the comments below, there's another way to get the higher bits. Instead of masking the lower bits then shifting, we can just shift.
int high = x >> 4;
Note that we don't need to mask the lower bits since whatever they were, they're gone (we've pushed them out). The above example is clearer since we explicitly zero them out first, but there's no need to do so for this particular example.
But to deal with numbers bigger than 16 bits (int is usually 32 bits), we still need to mask, because we can have the even higher sixteen bits getting in the way!
int high = (x >> 4) & 0x0F;

Related

bitparity code for odd number of bits

I came across this code while doing research for finding bit parity and have almost no idea why this works. Would anyone be able to enlighten me about its algorithm?
x ^= x >> 16
x ^= x >> 8
x ^= x >> 4
x ^= x >> 2
x ^= x >> 1
x &= 1;
The first line XORs the high 16 bits into the low 16 bits.
The second line XORs the the high half of the low 16 bits into the low half.
etc.
Before the last line, the low bit contains the parity of the initial 32 bits but the other bits contain intermediate results (garbage). The last line clears all of the garbage bits.
Each line takes half of the remaining values and XORs it into the other half. In total, because the XOR operation is associative and commutative, this works out the same as individually XORing each bit together.
You're folding 32-bits to 16-bits, then 16 to 8, ... and finally 2 to 1. So how does folding work? Well let's take a simple example starting with a 4-bit number (shown in binary)
x = 1110
To fold it with x ^= x >> 2 the calculation is
1110 // x three bits, odd parity
0011 // x >> 2
----
xx01 // after the XOR, ignoring the upper bits
At this point, we've folded 4-bits into 2, and we only care about the 2 lsbs which are 01. Note that the parity has been preserved, there's one bit set, and the parity is still odd. How did that happen? If you examine just the lower two bits, you see
10 // the lower two bits from the 4-bit number
11 // the upper two bits from the 4-bit number
01 // after exclusive-OR
The exclusive-OR converts the first column to 0, which removes two bits from the result, but keeps the parity the same. And that's why it works. The exclusive-OR reduces the total bit count by 2 any time you have two 1s in the same column. So if the original bit count was odd, the final bit count will be odd. If the original bit count was even, the final bit count will be even.
Continuing with the example, fold it again with x ^= x >> 1
01 // the lower 2 bits from the previous calculation
00 // shifted by one
--
x1 // after the XOR, ignoring the upper bits
The final piece of the puzzle is the x &= 1 at the end. That throws away all of the upper bits, leaving the one-bit result.

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.

How to flip a specific bit in a byte in C?

I'm trying to use masks and manipulating specific bits in a byte.
For example:
I want to write a program in C that flips two bits at particular positions e.g. the bit at position 0 and the one at the third position.
So, 11100011, would become 01110011.
How can I swap these bits?
Flipping a bit is done by XOR-ing with a mask: set bits at the positions that you want to flip, and then execute a XOR, like this:
int mask = 0x90; // 10010000
int num = 0xE3; // 11100011
num ^= mask; // 01110011
Here are a few notes:
bits are commonly counted from the least significant position, so your example flips bits in positions 4 and 7, not at positions 0 and 4
To construct a bit mask for a single position, use expression 1 << n, where n is the position number counting from the least significant bit.
To combine multiple bits in a single mask, use | operator. For example, (1 << 4) | (1 << 7) constructs the mask for flipping bits 4 and 7.
If your byte is x, and you want to switch the bits at the i-th and j-th position:
x = x ^ ((1<<i) | (1<<j));
So, in your case, it would just be (1<<4) | (1<<7). :)
First of all, good luck!
One remark - it is more useful to count the bits from the right and not left, since there are various byte/word sizes (8-bit,16-bit,etc.) and that count preserves compatibility better. So in your case you are referring to bits #7 and #4 (zero-count).
Did you mean 'flip' (change 0<->1 bits) or 'switch' them between one and the other?
For the first option, the answer above (XOR with "int mask = 0x90; // 10010000") is very good. For the second one, it's a bit more tricky (but not much).
To flip bits, you can use the exclusive OR bitwise operator. This takes two operands (typically, the value you want to operate on and the mask defining what bits will be flipped). The eXclusive OR (XOR) operator will only flip a bit if, and only if, one of the two is set to 1, but NOT both. See the (simple) example below:
#include <stdio.h>
int main(int argc, char** argv)
{
int num = 7; //00000111
int mask = 3; //00000011
int result = num ^ mask; //00000100
printf("result = %d\n", result); //should be 4
return 0;
}

How to create mask with least significat bits set to 1 in C

Can someone please explain this function to me?
A mask with the least significant n bits set to 1.
Ex:
n = 6 --> 0x2F, n = 17 --> 0x1FFFF // I don't get these at all, especially how n = 6 --> 0x2F
Also, what is a mask?
The usual way is to take a 1, and shift it left n bits. That will give you something like: 00100000. Then subtract one from that, which will clear the bit that's set, and set all the less significant bits, so in this case we'd get: 00011111.
A mask is normally used with bitwise operations, especially and. You'd use the mask above to get the 5 least significant bits by themselves, isolated from anything else that might be present. This is especially common when dealing with hardware that will often have a single hardware register containing bits representing a number of entirely separate, unrelated quantities and/or flags.
A mask is a common term for an integer value that is bit-wise ANDed, ORed, XORed, etc with another integer value.
For example, if you want to extract the 8 least significant digits of an int variable, you do variable & 0xFF. 0xFF is a mask.
Likewise if you want to set bits 0 and 8, you do variable | 0x101, where 0x101 is a mask.
Or if you want to invert the same bits, you do variable ^ 0x101, where 0x101 is a mask.
To generate a mask for your case you should exploit the simple mathematical fact that if you add 1 to your mask (the mask having all its least significant bits set to 1 and the rest to 0), you get a value that is a power of 2.
So, if you generate the closest power of 2, then you can subtract 1 from it to get the mask.
Positive powers of 2 are easily generated with the left shift << operator in C.
Hence, 1 << n yields 2n. In binary it's 10...0 with n 0s.
(1 << n) - 1 will produce a mask with n lowest bits set to 1.
Now, you need to watch out for overflows in left shifts. In C (and in C++) you can't legally shift a variable left by as many bit positions as the variable has, so if ints are 32-bit, 1<<32 results in undefined behavior. Signed integer overflows should also be avoided, so you should use unsigned values, e.g. 1u << 31.
For both correctness and performance, the best way to accomplish this has changed since this question was asked back in 2012 due to the advent of BMI instructions in modern x86 processors, specifically BLSMSK.
Here's a good way of approaching this problem, while retaining backwards compatibility with older processors.
This method is correct, whereas the current top answers produce undefined behavior in edge cases.
Clang and GCC, when allowed to optimize using BMI instructions, will condense gen_mask() to just two ops. With supporting hardware, be sure to add compiler flags for BMI instructions:
-mbmi -mbmi2
#include <inttypes.h>
#include <stdio.h>
uint64_t gen_mask(const uint_fast8_t msb) {
const uint64_t src = (uint64_t)1 << msb;
return (src - 1) ^ src;
}
int main() {
uint_fast8_t msb;
for (msb = 0; msb < 64; ++msb) {
printf("%016" PRIx64 "\n", gen_mask(msb));
}
return 0;
}
First, for those who only want the code to create the mask:
uint64_t bits = 6;
uint64_t mask = ((uint64_t)1 << bits) - 1;
# Results in 0b111111 (or 0x03F)
Thanks to #Benni who asked about using bits = 64. If you need the code to support this value as well, you can use:
uint64_t bits = 6;
uint64_t mask = (bits < 64)
? ((uint64_t)1 << bits) - 1
: (uint64_t)0 - 1
For those who want to know what a mask is:
A mask is usually a name for value that we use to manipulate other values using bitwise operations such as AND, OR, XOR, etc.
Short masks are usually represented in binary, where we can explicitly see all the bits that are set to 1.
Longer masks are usually represented in hexadecimal, that is really easy to read once you get a hold of it.
You can read more about bitwise operations in C here.
I believe your first example should be 0x3f.
0x3f is hexadecimal notation for the number 63 which is 111111 in binary, so that last 6 bits (the least significant 6 bits) are set to 1.
The following little C program will calculate the correct mask:
#include <stdarg.h>
#include <stdio.h>
int mask_for_n_bits(int n)
{
int mask = 0;
for (int i = 0; i < n; ++i)
mask |= 1 << i;
return mask;
}
int main (int argc, char const *argv[])
{
printf("6: 0x%x\n17: 0x%x\n", mask_for_n_bits(6), mask_for_n_bits(17));
return 0;
}
0x2F is 0010 1111 in binary - this should be 0x3f, which is 0011 1111 in binary and which has the 6 least-significant bits set.
Similarly, 0x1FFFF is 0001 1111 1111 1111 1111 in binary, which has the 17 least-significant bits set.
A "mask" is a value that is intended to be combined with another value using a bitwise operator like &, | or ^ to individually set, unset, flip or leave unchanged the bits in that other value.
For example, if you combine the mask 0x2F with some value n using the & operator, the result will have zeroes in all but the 6 least significant bits, and those 6 bits will be copied unchanged from the value n.
In the case of an & mask, a binary 0 in the mask means "unconditionally set the result bit to 0" and a 1 means "set the result bit to the input value bit". For an | mask, an 0 in the mask sets the result bit to the input bit and a 1 unconditionally sets the result bit to 1, and for an ^ mask, an 0 sets the result bit to the input bit and a 1 sets the result bit to the complement of the input bit.

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