This question already has answers here:
How do I set, clear, and toggle a single bit?
(27 answers)
Closed 7 years ago.
I wish to store either 0 or 1 in each bit of an allocated memory. For example I have char *block_of_memory = (char *)malloc(125000 * sizeof(char)) , here I have 125000 * 8 bits = 1000,000 bits of memory. How can I access each bit and give it a value as 0 or 1. Say , I want to make the 20th bit to 1 and 21st bit as 0.
You need to calculate a byte offset and a bitmask within that byte.
Set the bit: bitwise OR with mask
Clear the bit: bitwise AND with complement of mask
Read the bit: return bitwise AND of byte and mask
The code:
void set_bit(char *buf, int bit, int val)
{
int byte = bit / 8;
char mask = 1 << (bit % 8);
if (val)
buf[byte] |= mask;
else
buf[byte] &= ~mask;
}
int get_bit(char *buf, int bit)
{
int byte = bit / 8;
char mask = 1 << (bit % 8);
return buf[byte] & mask ? 1 : 0;
}
Example: Set bit 17 to 1. Byte offset is 17/8 = 2. Bit offset is 17%8 = 1. The bitmask is generated by left-shifting 1 by the bit offset: results in 00000010 binary. Bitwise OR byte[2] with it: all bits remain the same, except where the mask bit is 1.
Related
I want to write a function that receives an unsigned char and swaps between bit 2 and bit 4 and returns the new number.
I am not allowed to use if statement.
So I found this function, among other functions, but this was the most simple one to understand (or try to understand).
All other functions involve XOR which I don't really understand to be honest.
unsigned char SwapBits(unsigned char num)
{
unsigned char mask2 = ( num & 0x04 ) << 2;
unsigned char mask4 = ( num & 0x10 ) >> 2;
unsigned char mask = mask3 | mask5 ;
return ( num & 0xeb ) | mask;
}
Can someone explain me what happens here and most important, why?
Why AND is required here and why with hex address?
Why should I AND with 0xeb (255)? I know that's the range of char but why should I do that.
In short,
I know how to read codes. I understand this code, but I don't understand the purpose of each line.
Thanks.
First, the usual convention is that bits are numbered starting from 0 for the least significant bit and counting up. In this case, you have an 8-bit value, so the bits go from 0 on the right up to 7 on the left.
The function you posted still isn't quite right, but I think I see where you (it) was going with it. Here are the steps it's doing:
Pull out bit 2 (which is 3rd from the right) using a mask
Pull out bit 4 (which is 5th from the right) using a mask
Shift bit 2 left 2 positions so it's now in bit 4's original position
Shift bit 4 right 2 positions so it's now in bit 2's original position
Join these two bits together into one value that is now bits 2 and 4 swapped
Mask out (erase using &) only bits 2 and 4 from the original value
Join in (insert using |) the new swapped bits 2 and 4 to complete the transformation
I have rewritten the function to show each step one at a time to help make it clearer. In the original function or other examples you find, you'll see many of these steps all happen together in the same statement.
unsigned char SwapBits(unsigned char num)
{
// preserve only bit 2
unsigned char bit2 = num & 0x04;
// preserve only bit 4
unsigned char bit4 = num & 0x10;
// move bit 2 left to bit 4 position
unsigned char bit2_moved = bit2 << 2;
// move bit 4 right to bit 2 position
unsigned char bit4_moved = bit4 >> 2;
// put the two moved bits together into one swapped value
unsigned char swapped_bits = bit2_moved | bit4_moved;
// clear bits 2 and 4 from the original value
unsigned char num_with_swapped_bits_cleared = num & ~0x14;
// put swapped bits back into the original value to complete the swap
return num_with_swapped_bits_cleared | swapped_bits;
}
The second to last step num & ~0x14 probably needs some explanation. Since we want to save all the original bits except for bits 2 and 4, we mask out (erase) only the bits we're changing and leave all the others alone. The bits we want to erase are in positions 2 and 4, which are the 1s in the mask 0x14. So we do a complement (~) on 0x14 to turn it into all 1s everywhere except for 0s in bits 2 and 4. Then we AND this value with the original number, which has the effect of changing bits 2 and 4 to 0 while leaving all the others alone. This allows us to OR in the new swapped bits as the final step to complete the process.
You have to read about binary representation of number
unsigned char SwapBits(unsigned char num)
{
// let say that [num] = 46, it means that is is represented 0b00101110
unsigned char mask2 = ( num & 0x04 ) << 2;
// now, another byte named mask2 will be equal to:
// 0b00101110 num
// 0b00000100 0x04
// . .1. mask2 = 4. Here the & failed with . as BOTH ([and]) bits need to be set. Basically it keeps only numbers that have the 3rd bit set
unsigned char mask4 = ( num & 0x10 ) >> 2;
// 0b00101110 num
// 0b00010000 0x10 -> means 16 in decimal or 0b10000 in binary or 2^4 (the power is also the number of trailing 0 after the bit set)
// 0b00.....0 mask4 = 0, all bits failed to be both set
unsigned char mask = mask3 | mask5 ;
// mask will take bits at each position if either set by mask3 [or] mask5 so:
// 0b1001 mask3
// 0boo11 mask4
// 0b1011 mask
return ( num & 0xeb ) | mask; // you now know how it works ;) solve this one. PS: operation between Brackets have priority
}
If you are interested to learn the basics of bitwise operators you can take a look at this introduction.
After you build confidence you can try solving algorithms using only bitwise operators, where you will explore even deeper bitwise operations and see its impact on the runtime ;)
I also recommend reading Bit Twiddling Hacks, Oldies but Goodies!
b = ((b * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32; // reverse your byte!
Simple function to understand swap of bit 3 and 5:
if you want to swap bit index 3 and bit index 5, then you have to do the following:
int n = 0b100010
int mask = 0b100000 // keep bit index 5 (starting from index 0)
int mask2 = 0b1000 // keep bit index 3
n = (n & mask) >> 2 | (n & mask2) << 2 | (n & 0b010111);
// (n & mask) >> 2
// the mask index 5 is decrease by 2 position (>>2) and brings along with it the bit located at index 5 that it had captured in n thanks to the AND operand.
// | (n & mask2) << 2
// mask2 is increased by 2 index and set it to 0 since n didn't have a bit set at index 3 originally.
// | (n & 0b010111); // bits 0 1 2 and 4 are preserved
// since we assign the value to n all other bits would have been wiped out if we hadn't kept their original value thanks to the mask on which we do not perform any shift operations.
I'm very new to bit manipulations.
let's suppose I have a 32 bit value myInput4ByteValue.
From this 32 bit value I need to extract the bits 25 ..2
What would be the best approach here?
My Idea is to split them into 3 bytes and copy the values there:
struct myOutput3ByteValue.
{
uint8 FirstPart // Bits 9..2 Least Significant 8 Bits from myInput4ByteValue.
uint8 SecondPart // Bits 17 ..10
uint8 ThirdPart // Bits 25 ..18
}
I started with:
myOutput3ByteValue.FirstPart = (myInput4ByteValue & 0x3FC0) // Here I will the bits 9..2
myOutput3ByteValue.SecondPart = ...? //How to fill the rest?
I'm really not sure if I started correctly.
Suggestions would be helpful.
The reason why I split them into 3 bytes is because I will have an own 3 byte-type at the end with which I have to work with it.
What you've got there wont' quite work. 0x3FC0 is a 16 bit int and you're assigning it to an 8 bit int, so it'll get truncated. You need to bitshift << or >>.
So bits 9..2 are:
FirstPart = (value >> 1); // No need to mask as bits 9+ will be truncated
SecondPart = (value >> 9); // Second set of 8 bits
Let's assume you want to put the extracted bits in a single UINT32 variable. What you need is simply to filter first 26 bits and shift them twice:
uint32 filteredValue = ( myInput4ByteValue & 0x03FFFFFF ) >> 2;
With the same logic, you can extract whatever you need and place them in any set of variable, according to the use you have to do wit the filtered bits.
You might want to define a general function performing the bits extraction:
uint32 filterValue( uint32 inValue, uint8 msb, uint8 lsb )
{
uint32 retValue = inValue;
// Let's just check that input params are ok
if( msb < 32 && lsb <32 && msb >= lsb )
{
retValue = ( inValue & ( 0xFFFFFFFF >> ( 31 - msb ) >> lsb;
}
//else... input value unchanged. It doesn't make sense, but it's just an example..
return retValue;
}
I personally wrote and tested it, and it works. Note: it's just an example! Change it according to your requirements.
myInput4ByteValue & 0x3FFFFFF extracts the last 26 bits (the leftmost bit would be bit 25, as one usually starts counting from the right with bit 0).
(myInput4ByteValue & 0x3FFFFFF) >> 2 shifts bits these two places to the right. This would hold your complete 23 bits.
If, however you want to have everything in 8-bit chunks, you could do:
myOutput3ByteValue.FirstPart = (myInput4ByteValue & 0x7F8) >> 2; // bits 9..2
myOutput3ByteValue.SecondPart = (myInput4ByteValue & 0x7F800) >> 10; // bits 17..10
myOutput3ByteValue.ThirdPart = (myInput4ByteValue & 0x3F80000) >> 18; // bits 25..18
Another approach, which could be much easier to read and maintain, is the use of bitfields. See e.g. http://www.catb.org/esr/structure-packing/#_bitfields .
Depending on whether individual bits or groups of bits have a particular meaning, you can give them their own name. If you align the structure nicely, you can simply copy the 32 bit input upon a variable with such a struct as type.
Just write a separate function that extracts no more than 8 bits starting from a given position from a number of the type uint32_t.
Here is a demonstrative program
#include <stdio.h>
#include <stdint.h>
uint8_t getbits( uint32_t x, unsigned p, unsigned n)
{
const unsigned N = 8;
n %= N + 1;
return ( x >> p ) & ~( ~( uint32_t )0 << n );
}
int main(void)
{
uint32_t x = 0x12345678;
/*0001 0010 0011 0100 0101 0110 0111 1000 */
/* ^^^^^^^^^^ = 0x9E */
struct myOutput3ByteValue
{
uint8_t FirstPart; // Bits 9..2 Least Significant 8 Bits from myInput4ByteValue.
uint8_t SecondPart; // Bits 17 ..10
uint8_t ThirdPart; // Bits 25 ..18
} s =
{
.FirstPart = getbits( x, 2, 8 ),
.SecondPart = getbits( x, 10, 8 ),
.ThirdPart = getbits( x, 18, 8 )
};
printf( "%x, %x, %x\n", s.FirstPart, s.SecondPart, s.ThirdPart );
return 0;
}
Its output is
9e, 15, 8d
I'm trying to convert numbers to binary and then fwrite the binary numbers to binary file.
Assuming all numbers are 7 bits numbers (int numbers < 127).
So in the end, the file will contain the numbers as blocks of 7 bits
I know that each BYTE is 8 bits, and i can't to write each number to 1 BYTE, but need to use the whole BYTE (i.e some of the numbers will be in 2 different BYTES)
if : 120 = 1111000 | 7 = 0000111 | 64 = 1000000
so the bit stream is 111100000001111000000 and should be written as
1111000|0 000111|10 00000|00
1BYTE 2BYTE 3BYTE
I thought to use a buffer
shifting 8 bits to buffer and then fwrite to the file, using pointers
But i just can't mange to write it. Thank you for your help
First, when dealing with bits use unsigned integers
unsigned char a = 0;
char bits[] = "1111000";
char *p = bits;
while (*p) {
a <<= 1; // shift left
a |= (*p == '1'); // add bit
p++; // next bit
}
So, you want to put 8 7-bit values in 7 8-bit locations
[-val-][-val-][-val-]...
00000001111111222222233333334444444555555566666667777777
[-loc8-][-loc8-][-loc8-]...
Just map bits and you're done
For example, the 3rd 7-bit value (assuming int val7[8]) can be written into the 8-bit locations (assuming int loc8[7]) with
loc8[1] &= 0xfc; // clear 2 bits
loc8[1] |= (val7[2] & 0x60) >> 5; // set 2 bits
loc8[2] &= 0x7; // clear 5 bits
loc8[2] |= (val7[2] & 0x1f) << 3; // set 5 bits
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));
}
There's a variable:
char segment = 0;
After 1 or with bit 15, segment = 1;
Just means this bit check already.
Question is how to cancel the mark of bit 15 (set back to 0)?
Use "~"?
Following program sets bit, clears bit and toggles bit
#include<stdio.h>
void main(void)
{
unsigned int byte;
unsigned int bit_position;
unsigned int tempbyte = 0x01;
//get the values of the byte and the bit positions
//set bit
byte = (byte | (tempbyte << bit_position));// set the bit at the position given by bit_position
//clear bit
byte = (byte & ~(tempbyte << bit_position));//clear the bit at the position given by bit_position
//toggle bits
byte = (byte ^ (tempbyte << bit_position));//toggle the bit at the position given by bit_position
}
To get rid of the MSB of an 8-bit character for example, you can AND with 0x7F
e.g. segment = segment & 0x7F;
To dynamically produce the mask, you can use bit shifting operations (i.e. the << operator).