This question already has answers here:
How do I set, clear, and toggle a single bit?
(27 answers)
Closed 8 years ago.
I would like to set the i-th bit to zero no matter what the i-th bit is.
unsigned char pt = 0b01100001;
pt[0] = 0; // its not how we do this...
Setting it to one, we can use a mask pt | (1 << i) but i'm not sure how to create a mask for setting 0, if thats possible.
You just have to replace the logical OR with a logical AND operation. You would use the & operator for that:
pt = pt & ~(1 << i);
You have to invert your mask because logical ANDing with a 1 will maintain the bit while 0 will clear it... so you'd need to specify a 0 in the location that you want to clear. Specifically, doing 1 << i will give you a mask that is 000...010..000 where the 1 is in the bit position that you want, and inverting this will give 111...101...111. Logical ANDing with this will clear the bit that you want.
You could stick with this:
// Set bit at position `bitpos` in `pt` to `bitval`
unsigned char bitpos = 1;
unsigned char pt = 0b01100001;
bool bitval = 1;
// Clear the bit
pt &= ~(1u << bitpos);
// Set the bit
pt |= (bitval << bitpos);
Related
I understand what the individual operations are (such as the bitwise ANDs an ORs), but I don't understand why they have been used where they have been.
Also, my understanding is that the first set of masks are used to compute parity bits. But I don't understand why the 2nd set of masks have been chosen or what their purpose is. Can anyone help me get my head around this please?
rawData is the input word that is to be encoded by the hamming.c function.
Doing the encoding of a [31,26] Hamming code, the function hammingEncode() encodes a message rawData consisting of 26 message bits by inserting 5 parity bits on positions 0, 1, 3, 7 and 15 (counting bits starting from 0).
The purpose of the part you are asking about:
unsigned int mask1 = 0b11111111111111100000000000;
unsigned int mask2 = 0b00000000000000011111110000;
unsigned int mask3 = 0b00000000000000000000001110;
unsigned int mask4 = 0b00000000000000000000000001;
encodedData |= (rawData & mask1) << 5;
encodedData |= (rawData & mask2) << 4;
encodedData |= (rawData & mask3) << 3;
encodedData |= (rawData & mask4) << 2;
is to move the 26 message bits into the correct positions: 16-30, 8-14, 4-6 and 2 using mask1, mask2, mask3 and mask4 respectively.
After that, the parity bits are calculated and inserted on their correct positions.
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.
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.
My objective is to frame a char variable by assigning values to each bit, i.e. I need to assign 0's and 1's to each bit.
I did the following code:
char packet;
int bit;
packet &= ~(1 << 0);
packet |= (1 << 1);
printf("\n Checking each bit of packet: \n");
for(int x=0;x<2;x++)
{
bit = packet & (1 << x);
printf("\nBit [%d] of packet : %d", x, bit);
}
But the output I am getting is:
Bit[0] of packet : 0
Bit[1] of packet : 2
What is the problem here?
There's no problem here, the output is correct.
Here's the reason:
When you set the value of packet with |=, the value is 10 which, in decimal, is 2. When you assign packet & (1 << x) to bit, you're actually assigning the value 2 (10 in binary).
Wikipedia entry:
To determine whether the second bit is
1, a bitwise AND is applied to it and
another bit pattern containing 1 in
the second bit:
0011 (decimal 3)
AND 0010 (decimal 2)
= 0010 (decimal 2)
If your intent is to simply check a boolean value of whether or not the bit has been set, simply cast it to a bool value.
(Hope that all made sense, I'm a little tired atm ;))
First thing:
char packet;
packet &= ~(1 << 0);
This is not reliable, since packet starts off with whatever was in memory last (i.e. garbage). 1 << 0 is just 1. ~1 is ...111110. Anding that with packet will give a different answer each time, depending on what was in memory last; the only sure thing is that the last bit (i.e. least significant) will be set to 0.
packet |= (1 << 1);
This just sets the second bit to 1. So now packet is xxxxxx10.
Your loop then goes over the first two bits; each bit is masked with packet & (1 << x), but that only masks it, it does not move it around. So during the first iteration, 1 << x is 1, and you get the first bit (0). The second iteration, 1 << x is 10, or 2 in decimal. Anding xxxxxx10 with 10 gives 10, which you promptly print out (it appears formatted as 2).
If you want to move the bit (in order to isolate it as a 0 or 1), you can use:
bit = (packet & (1 << x)) >> x;
Or the equivalent but more readable
bit = (packet >> x) & 1;
This will yield the (I'm assuming desired) output of 0, 1 instead of 0, 2.
That output appears entirely expected. Bit 0 isn't set, Bit 1 is set. Perhaps you're after
bit = !!(packet & (1 << x));
...if you want to get an 0 or 1 result.
By the way, you should initialise packet - use of an uninitialised variable results in undefined behaviour.
I'm trying to implement a data compression idea I've had, and since I'm imagining running it against a large corpus of test data, I had thought to code it in C (I mostly have experience in scripting languages like Ruby and Tcl.)
Looking through the O'Reilly 'cow' books on C, I realize that I can't simply index the bits of a simple 'char' or 'int' type variable as I'd like to to do bitwise comparisons and operators.
Am I correct in this perception? Is it reasonable for me to use an enumerated type for representing a bit (and make an array of these, and writing functions to convert to and from char)? If so, is such a type and functions defined in a standard library already somewhere? Are there other (better?) approaches? Is there some example code somewhere that someone could point me to?
Thanks -
Following on from what Kyle has said, you can use a macro to do the hard work for you.
It is possible.
To set the nth bit, use OR:
x |= (1 << 5); // sets the 6th-from
right
To clear a bit, use AND:
x &= ~(1 << 5); // clears
6th-from-right
To flip a bit, use XOR:
x ^= (1 << 5); // flips 6th-from-right
Or...
#define GetBit(var, bit) ((var & (1 << bit)) != 0) // Returns true / false if bit is set
#define SetBit(var, bit) (var |= (1 << bit))
#define FlipBit(var, bit) (var ^= (1 << bit))
Then you can use it in code like:
int myVar = 0;
SetBit(myVar, 5);
if (GetBit(myVar, 5))
{
// Do something
}
It is possible.
To set the nth bit, use OR:
x |= (1 << 5); // sets the 5th-from right
To clear a bit, use AND:
x &= ~(1 << 5); // clears 5th-from-right
To flip a bit, use XOR:
x ^= (1 << 5); // flips 5th-from-right
To get the value of a bit use shift and AND:
(x & (1 << 5)) >> 5 // gets the value (0 or 1) of the 5th-from-right
note: the shift right 5 is to ensure the value is either 0 or 1. If you're just interested in 0/not 0, you can get by without the shift.
Have a look at the answers to this question.
Theory
There is no C syntax for accessing or setting the n-th bit of a built-in datatype (e.g. a 'char'). However, you can access bits using a logical AND operation, and set bits using a logical OR operation.
As an example, say that you have a variable that holds 1101 and you want to check the 2nd bit from the left. Simply perform a logical AND with 0100:
1101
0100
---- AND
0100
If the result is non-zero, then the 2nd bit must have been set; otherwise is was not set.
If you want to set the 3rd bit from the left, then perform a logical OR with 0010:
1101
0010
---- OR
1111
You can use the C operators && (for AND) and || (for OR) to perform these tasks. You will need to construct the bit access patterns (the 0100 and 0010 in the above examples) yourself. The trick is to remember that the least significant bit (LSB) counts 1s, the next LSB counts 2s, then 4s etc. So, the bit access pattern for the n-th LSB (starting at 0) is simply the value of 2^n. The easiest way to compute this in C is to shift the binary value 0001 (in this four bit example) to the left by the required number of places. As this value is always equal to 1 in unsigned integer-like quantities, this is just '1 << n'
Example
unsigned char myVal = 0x65; /* in hex; this is 01100101 in binary. */
/* Q: is the 3-rd least significant bit set (again, the LSB is the 0th bit)? */
unsigned char pattern = 1;
pattern <<= 3; /* Shift pattern left by three places.*/
if(myVal && (char)(1<<3)) {printf("Yes!\n");} /* Perform the test. */
/* Set the most significant bit. */
myVal |= (char)(1<<7);
This example hasn't been tested, but should serve to illustrate the general idea.
To query state of bit with specific index:
int index_state = variable & ( 1 << bit_index );
To set bit:
varabile |= 1 << bit_index;
To restart bit:
variable &= ~( 1 << bit_index );
Try using bitfields. Be careful the implementation can vary by compiler.
http://publications.gbdirect.co.uk/c_book/chapter6/bitfields.html
IF you want to index a bit you could:
bit = (char & 0xF0) >> 7;
gets the msb of a char. You could even leave out the right shift and do a test on 0.
bit = char & 0xF0;
if the bit is set the result will be > 0;
obviousuly, you need to change the mask to get different bits (NB: the 0xF is the bit mask if it is unclear). It is possible to define numerous masks e.g.
#define BIT_0 0x1 // or 1 << 0
#define BIT_1 0x2 // or 1 << 1
#define BIT_2 0x4 // or 1 << 2
#define BIT_3 0x8 // or 1 << 3
etc...
This gives you:
bit = char & BIT_1;
You can use these definitions in the above code to sucessfully index a bit within either a macro or a function.
To set a bit:
char |= BIT_2;
To clear a bit:
char &= ~BIT_3
To toggle a bit
char ^= BIT_4
This help?
Individual bits can be indexed as follows.
Define a struct like this one:
struct
{
unsigned bit0 : 1;
unsigned bit1 : 1;
unsigned bit2 : 1;
unsigned bit3 : 1;
unsigned reserved : 28;
} bitPattern;
Now if I want to know the individual bit values of a var named "value", do the following:
CopyMemory( &input, &value, sizeof(value) );
To see if bit 2 is high or low:
int state = bitPattern.bit2;
Hope this helps.
There is a standard library container for bits: std::vector. It is specialised in the library to be space efficient. There is also a boost dynamic_bitset class.
These will let you perform operations on a set of boolean values, using one bit per value of underlying storage.
Boost dynamic bitset documentation
For the STL documentation, see your compiler documentation.
Of course, you can also address the individual bits in other integral types by hand. If you do that, you should use unsigned types so that you don't get undefined behaviour if decide to do a right shift on a value with the high bit set. However, it sounds like you want the containers.
To the commenter who claimed this takes 32x more space than necessary: boost::dynamic_bitset and vector are specialised to use one bit per entry, and so there is not a space penalty, assuming that you actually want more than the number of bits in a primitive type. These classes allow you to address individual bits in a large container with efficient underlying storage. If you just want (say) 32 bits, by all means, use an int. If you want some large number of bits, you can use a library container.