How can I access a specific group of bits from a variable? - c

I have a variable with "x" number of bits. How can I extract a specific group of bits and then work on them in C?

You would do this with a series of 2 bitwise logical operations.
[[Terminology MSB (msb) is the most-significant-bit; LSB (lsb) is the least-significant-bit. Assume bits are numbered from lsb==0 to some msb (e.g. 31 on a 32-bit machine). The value of the bit position i represents the coefficient of the 2^i component of the integer.]]
For example if you have int x, and you want to extract some range of bits x[msb..lsb] inclusive, for example a 4-bit field x[7..4] out of the x[31..0] bits, then:
By shifting x right by lsb bits, e.g. x >> lsb, you put the lsb bit of x in the 0th (least significant) bit of the expression, which is where it needs to be.
Now you have to mask off any remaining bits above those designated by msb. The number of such bits is msb-lsb + 1. We can form a bit mask string of '1' bits that long with the expression ~(~0 << (msb-lsb+1)). For example ~(~0 << (7-4+1)) == ~0b11111111111111111111111111110000 == 0b1111.
Putting it all together, you can extract the bit vector you want with into a new integer with this expression:
(x >> lsb) & ~(~0 << (msb-lsb+1))
For example,
int x = 0x89ABCDEF;
int msb = 7;
int lsb = 4;
int result = (x >> lsb) & ~(~0 << (msb-lsb+1));
// == 0x89ABCDE & 0xF
// == 0xE (which is x[7..4])
Make sense?
Happy hacking!

If you're dealing with a primitive then just use bitwise operations:
int bits = 0x0030;
bool third_bit = bits & 0x0004; // bits & 00000100
bool fifth_bit = bits & 0x0010; // bits & 00010000
If x can be larger than a trivial primitive but is known at compile-time then you can use std::bitset<> for the task:
#include<bitset>
#include<string>
// ...
std::bitset<512> b(std::string("001"));
b.set(2, true);
std::cout << b[1] << ' ' << b[2] << '\n';
std::bitset<32> bul(0x0010ul);
If x is not known at compile-time then you can use std::vector<unsigned char> and then use bit-manipulation at runtime. It's more work, the intent reads less obvious than with std::bitset and it's slower, but that's arguably your best option for x varying at runtime.
#include<vector>
// ...
std::vector<unsigned char> v(256);
v[2] = 1;
bool eighteenth_bit = v[2] & 0x02; // second bit of third byte

work on bits with &, |. <<, >> operators.
For example, if you have a value of 7 (integer) and you want to zero out the 2nd bit:
7 is 111
(zero-ing 2nd bit AND it with 101 (5 in decimal))
111 & 101 = 101 (5)
here's the code:
#include <stdio.h>
main ()
{
int x=7;
x= x&5;
printf("x: %d",x);
}
You can do with other operators like the OR, shift left, shift right,etc.

You can use bitfields in a union:
typedef union {
unsigned char value;
struct { unsigned b0:1,b1:1,b2:1,b3:1,b4:1,b5:1,b6:1,b7:1; } b;
struct { unsigned b0:2,b1:2,b2:2,b3:2; } b2;
struct { unsigned b0:4,b1:4; } b4;
} CharBits;
CharBits b={0},a={0};
printf("\n%d",b.value);
b.b.b0=1; printf("\n%d",b.value);
b.b.b1=1; printf("\n%d",b.value);
printf("\n%d",a.value);
a.b4.b1=15; printf("\n%d",a.value); /* <- set the highest 4-bit-group with one statement */

Related

Invert specific bits using bitwise NOT (no XOR)

How can I use Bitwise Not to invert specific bits for x number? I know we can do this use XOR and mask but question requires use NOT.
I need to invert a group of bits starting at a given position. The variable inside the function includes original value, position wants to start and width = number of bits I want to invert.
I use the shift bit to start from a given position but how can I ensure only x number of bits are inverted using NOT Bitwise function?
Definition of xor: a ^ b <--> (a & ~b) | (~a & b)
unsigned x = 0x0F;
unsigned mask = 0x44; // Selected bits to invert
unsigned selected_x_bits_inverted = (x & ~mask) | (~x & mask);
printf("%02X\n", selected_x_bits_inverted);
// 4B
An approach would be:
First, extract them into y:
y = x & mask
Then, invert y and get only the bits you need:
y = ~y & mask
Clear the bits extracted from x:
x = x & (~mask)
OR those 2 numbers to get the result:
x = x | y
Note that every bit that has to be inverted is 1 in mask. Even if I used other bitwise operators, the actual bit flipping is done by a bitwise not. Also, I don't think it is possible to achieve this result without using some other binary operators.
This function will invert 'width' number of bits of number 'num' from position 'pos'
int invert(int num, int pos, int width)
{
int mask = (~((~0) << width)) << pos;
num = (~(num & mask)) & mask);
}

How do I extract bits from 32 bit number

I have do not have much knowledge of C and I'm stuck with a problem since one of my colleague is on leave.
I have a 32 bit number and i have to extract bits from it. I did go through a few threads but I'm still not clear how to do so. I would be highly obliged if someone can help me.
Here is an example of what I need to do:
Assume hex number = 0xD7448EAB.
In binary = 1101 0111 0100 0100 1000 1110 1010 1011.
I need to extract the 16 bits, and output that value. I want bits 10 through 25.
The lower 10 bits (Decimal) are ignored. i.e., 10 1010 1011 are ignored.
And the upper 6 bits (Overflow) are ignored. i.e. 1101 01 are ignored.
The remaining 16 bits of data needs to be the output which is 11 0100 0100 1000 11 (numbers in italics are needed as the output).
This was an example but I will keep getting different hex numbers all the time and I need to extract the same bits as I explained.
How do I solve this?
Thank you.
For this example you would output 1101 0001 0010 0011, which is 0xD123, or 53,539 decimal.
You need masks to get the bits you want. Masks are numbers that you can use to sift through bits in the manner you want (keep bits, delete/clear bits, modify numbers etc). What you need to know are the AND, OR, XOR, NOT, and shifting operations. For what you need, you'll only need a couple.
You know shifting: x << y moves bits from x *y positions to the left*.
How to get x bits set to 1 in order: (1 << x) - 1
How to get x bits set to 1, in order, starting from y to y + x: ((1 << x) -1) << y
The above is your mask for the bits you need. So for example if you want 16 bits of 0xD7448EAB, from 10 to 25, you'll need the above, for x = 16 and y = 10.
And now to get the bits you want, just AND your number 0xD7448EAB with the mask above and you'll get the masked 0xD7448EAB with only the bits you want. Later, if you want to go through each one, you'll need to shift your result by 10 to the right and process each bit at a time (at position 0).
The answer may be a bit longer, but it's better design than just hard coding with 0xff or whatever.
OK, here's how I wrote it:
#include <stdint.h>
#include <stdio.h>
main() {
uint32_t in = 0xd7448eab;
uint16_t out = 0;
out = in >> 10; // Shift right 10 bits
out &= 0xffff; // Only lower 16 bits
printf("%x\n",out);
}
The in >> 10 shifts the number right 10 bits; the & 0xffff discards all bits except the lower 16 bits.
I want bits 10 through 25.
You can do this:
unsigned int number = 0xD7448EAB;
unsigned int value = (number & 0x3FFFC00) >> 10;
Or this:
unsigned int number = 0xD7448EAB;
unsigned int value = (number >> 10) & 0xFFFF;
I combined the top 2 answers above to write a C program that extracts the bits for any range of bits (not just 10 through 25) of a 32-bit unsigned int. The way the function works is that it returns bits lo to hi (inclusive) of num.
#include <stdio.h>
#include <stdint.h>
unsigned extract(unsigned num, unsigned hi, unsigned lo) {
uint32_t range = (hi - lo + 1); //number of bits to be extracted
//shifting a number by the number of bits it has produces inconsistent
//results across machines so we need a special case for extract(num, 31, 0)
if(range == 32)
return num;
uint32_t result = 0;
//following the rule above, ((1 << x) - 1) << y) makes the mask:
uint32_t mask = ((1 << range) -1) << lo;
//AND num and mask to get only the bits in our range
result = num & mask;
result = result >> lo; //gets rid of trailing 0s
return result;
}
int main() {
unsigned int num = 0xd7448eab;
printf("0x%x\n", extract(num, 10, 25));
}

Bit masking and separation in c

I am new to c programming and i need help in bit manipulation.
I would like to separate the number from a register which have encoded numbers in BCD.
for example;
the register got '29' as value two bits will denote 2 ='10' and four bits will denote 9='1001'.
It is an 8 bit register and rest bits are zero.
So shifting out the 4 bits will give me 2 at disposal.But what about getting the unit digit?
I need some help regarding that
I'm posting the code here:
#include<stdio.h>
main()
{
int x,y;
y=0x29;
x=y;
x=x>>4;
x=x*10;
printf("%d",x);
return(0);
}
You need to mask it out with binary 00001111, which is decimal 15 or hexadecimal 0x0f.
uint8_t reg = 41; // binary 00101001
uint8_t lo_nibble = (reg >> 0) & 0x0f;
uint8_t hi_nibble = (reg >> 4) & 0x0f;
To form a mask to capture the bottom n bits of a number, you can perform these steps (pen and paper at first, eventually in your head):
start with the value 1.
(1) // == 1 or 00000001
shift the value 1 up by n bits.
(1<<4) // == 16 or 00010000
subtract 1.
(1<<4)-1 // == 15 or 00001111
ANDing this mask with another value or variable will yield the bottom n bits of the number.
int in, hi, lo;
lo = in & ((1<<4)-1);
hi = (in>>4) & ((1<<4)-1);

Exchange the bytes

I want to exchange the bytes of a number. Example the binary representation of a number is
00000001 00011000 00000100 00001110. I want to reverse it: 00001110 00000100 00011000 00000001.
Can you please help? The current code is below:
void showBits(int n)
{
int i,k,andMask;
for(i=15;i>=0;i--)
{
andMask=1<<i;
k=n&andMask;
k==0?(cout<<"0"):(cout<<"1");
}
}
int reverse(int a)
{
int b=a<<8;
int c=a>>8;
return (b|c);
}
int main()
{
int a=10;
showBits(a);
int b=reverse(a);
showBits(b);
cin.get();
}
Something like this should work:
result = ((number & 0xFF) << 24) | ((number & 0xFF00) << 8) |
((number & 0xFF0000) >> 8) | ((number & 0xFF000000) >> 24);
int myInt = 0x012345678
__asm {
mov eax, myInt
bswap eax
mov myInt, eax
}
If you want to simply reverse a 32-bit number, you can use a bit-shifting technique that isolates each byte region using bit-masks and logical AND, and then swaps those bytes by the appropriate number of shifted bits using the bit-shift operators >> and <<. You can then recombined the bits using logical OR like so:
int temp = 0x12345678;
temp = ((0xFF & temp) << 24) | ((0xFF00 & temp) << 8) | ((0xFF0000 & temp) >> 8) |
((0xFF000000 & temp) >> 24));
You'll now end up with a final value in temp of 0x78563412.
Update: Okay, I'm looking over you code, and noting the following:
The size of int it seems like you're wanting to work with from the binary digit you have posted is 32-bits ... so your showBits function is not cycling through enough bits to display an entire 32-bit integer. As far as I can see right now, it will only show up to the 16 lower bits. So you'll need to be clear on whether you're working on a platform that defines int as 16 or 32-bits.
Your reverse functions is not correct. If you have a 32-bit int like 0x12345678, and you shift it left by 8-bits, you will end up with 0x34567800. Likewise, when you shift it right by 8-bits, you will just end up with 0x00123456. Shifting a number does not rotate the values through their respective positions (i.e., a shift left of 8-bits would not give you 0x34567812). Plus, even if it did, the logical OR of the rotated values would still not be a correct reversal of the values. Instead, you must use the technique described above that uses bit-masks and logical AND to isolate each byte, and then shift those bits the appropriate number of places in order to reverse the bits in a 32-bit word.
If your original task to to convert from machine-specific byte order to big endian and back, take a look at the hton* and ntoh* functions.
http://minix1.woodhull.com/manpages/man3/hton.3.html

Introducing errors by flipping bits

I have a character array in C into which I want to introduce errors by flipping some bits.
How can I flip bits and introduce errors?
You can flip bits using the xor operator:
x = x ^ mask;
x ^= mask; // Same functionality as above.
For example, if mask is 1, the least significant bit is flipped. You can create any desired mask by bit-shifting the 1: mask = 1 << k; where k is the number of bits to shift.
For distributing the errors, use a random number generator. rand() / srand() should suffice if this is for test purposes.
To flip a bit you can use the bit shifting and bitwise xor operators.
unsigned char flip(unsigned char c, int bit) {
return c ^ (1 << bit);
}
You can also flip more than one bit by using a bitmask other than (1 << bit), which has just one bit set:
unsigned char flip(unsigned char c, unsigned char mask) {
return c ^ (1 << mask);
}
// flip bits 0 and 3 (00001001 = 0x09)
flip(c, 0x09);

Resources