can we access the bits shifted by bit shifting operators(<<, >>) in C, C++?
For example:
23>>1
can we access the last bit shifted(1 in this case)?
No, the shift operators only give the value after shifting. You'll need to do other bitwise operations to extract the bits that are shifted out of the value; for example:
unsigned all_lost = value & ((1 << shift)-1); // all bits to be removed by shift
unsigned last_lost = (value >> (shift-1)) & 1; // last bit to be removed by shift
unsigned remaining = value >> shift; // lose those bits
By using 23>>1, the bit 0x01 is purged - you have no way of retrieving it after the bit shift.
That said, nothing's stopping you from checking for the bit before shifting:
int value = 23;
bool bit1 = value & 0x01;
int shifted = value >> 1;
You can access the bits before shifting, e.g.
value = 23; // start with some value
lsbits = value & 1; // extract the LSB
value >>= 1; // shift
It worth signal that on MSVC compiler an intrinsic function exists: _bittest
that speeds up the operation.
Related
Let's say I have a 64-bit number and some bits that are set that hold a value, let's say three bits. I have a mask to get that value. To get the value of those three bits I bitwise 'AND' the number with the mask. This sets all other bits to zero. I then need to shift right towards the least significant bits so the least significant bit of the three-bit number is in the position of the least significant bit of the 64 bit number. After I shift right, do I need to mask again to ensure only all the bits to the left of those three bits are zero?
You can do shift first then the mask and accomplish what you want:
int value = 0xdeadbeef;
value >>= 15;
value &= 0x7;
In prior versions of the C++ standard, right-shifts of negative values were implementation-defined because signed integers could be one's-complement, two's-complement or sign+magnitude. So the behavior of right shift of a negative was implementation defined.
But all implementations of (modern) C++ are for CPUs using two's-complement and a lot of existing code relies on that implementation detail. In C++ 2020 this was finally acknowledged and signed integers are now defined as two's-complement.
The way shift right works depends on the type of the argument:
int value = -1;
value >>= 10;
Assuming two's-complement, which is now required, this will use an arithmetic shift and preserves the sign bit. So after the shift the value will still be -1 and have all bits set. If you mask before the shift then after the shift you get more bits then you bargained for.
unsigned int value = 0xFFFFFFFF;
value >>= 10;
This will use a logical shift and add zeroes to the left. So if you mask before the shift then you still get the right bits after the shift.
But why mask before the shift? If you mask after the shift then you always get the right bits regardless of the type.
Do I have to set most significant bits to zero if I shift right?
After I shift right, do I need to mask again to ensure only all the bits to the left of those three bits are zero?
Yes, if the result of the mask was a signed type, a mask needed to cope with the sign bit shifted.
No if the result of the mask was a unsigned type.
uint64_t mask = ...;
uint64_t masked_value = mask & value;
uint64_t final = masked_value >> shift_amount;
If code did:
int64_t mask = 7 << shift_amount;
int64_t masked_value = mask & value;
int64_t almost_final = masked_value >> shift_amount;
int final = (int) (masked_value & 7);
A smart compiler may emit efficient as as the unsigned approach above.
I want to shift left only one bit in a specific place leaving its position 0, so I do not want to shift the whole variable with << operator, here is an example: say the variable has the value 1100 1010 and I want to shift the fourth bit then the result should be 1101 0010.
Steps to get there.
Pull out bit value from the original number.
Left shift the bit value by one.
Merge the bit-shifted value back to the original number.
// Assuming C++14 or later to be able to use the binary literal integers
int a = 0b11001010;
int t = a & 0b00001000; // Pull out the 4-th bit.
t <<= 1; // Left shift the 4-th bit.
a = a & 0b11100111; // Clear the 4-th and the 5-th bit
a |= t; // Merge the left-shifted 4-th bit.
For C++, I'd just use a std::bitset. Since you set the bit of pos + 1 to the value of the bit at pos, and then set the bit at pos to 0 this translate into bitset code that is quite easy to read. That would give you a function like
unsigned char shift_bit_bitset(unsigned char val, unsigned pos)
{
std::bitset<8> new_val(val);
new_val[pos + 1] = new_val[pos];
new_val[pos] = 0;
return new_val.to_ulong();
}
Maybe not the shortest/cleanest way, but this'll do it:
unsigned shift_bit = 4;
unsigned char val = 0xCA; // 1100 1010
unsigned char bit_val = val & (1 << shift_bit - 1); // Get current bit value
val = val & ~(1 << shift_bit - 1); // Clear initial bit location
val = bit_val ? // Update next bit to 0 or 1
val | (1 << shift_bit) :
val & ~(1 << shift_bit);
See it work with the test cases specified in your question and comments here: ideone
A simpler way is
(x & 0b11101111) + (x & 0b00001000)
that is, clear the bit that will be shifted into and add the bit to be shifted, which will overflow to the left if it is 1.
I know that to get the first j least significant bits of an integer you can do the following:
int res = (myInteger & ((1<<j)-1))
Can you do something similar for the most significant bits?
Simply right shift: (Warning, fails when you want 0 bits, but yours fails for all bits)
unsigned dropbits = CHAR_BIT*sizeof(int)-j;
//if you want the high bits moved to low bit position, use this:
ullong res = (ullong)myInteger >> dropbits;
//if you want the high bits in the origonal position, use this:
ullong res = (ullong)myInteger >> dropbits << dropbits;
Important! The cast must be the unsigned version of your type.
It's also good to note that your code for the lowest j bits fails when you ask it for all (32?) bits. As such, it can be easier to doubleshift:
unsigned dropbits = CHAR_BIT*sizeof(int)-j;
ullong res = (ullong)myInteger << dropbits >> dropbits;
See it working here: http://coliru.stacked-crooked.com/a/64eb843b3b255278 and here: http://coliru.stacked-crooked.com/a/29bc40188d852dd3
To get the j highest bits of an integer (or rather an unsigned integer, because bitwise operations in signed integers are a recipe for pain):
unsigned res = myUnsignedInteger & ~(~0u >> j);
~0u consists of only set bits. Shifting that j bits to the right gives us j zero-bits on the left side followed by one-bits, and inverting that gives us j one-bits on the left followed by zeroes, which is the mask we need to isolate the j highest bits of another integer.
Note: This is under the assumption that you want the isolated bits to remain in the same place, which is to say
(0xdeadbeef & ~(~0u >> 12)) == 0xdea00000
Let's say I've got a uint16_t variable where I must set specific bits.
Example:
uint16_t field = 0;
That would mean the bits are all zero: 0000 0000 0000 0000
Now I get some values that I need to set at specific positions.
val1=1; val2=2, val3=0, val4=4, val5=0;
The structure how to set the bits is the following
0|000| 0000| 0000 000|0
val1 should be set at the first bit on the left. so its only one or zero.
val2 should be set at the next three bits. val3 on the next four bits. val4 on the next seven bits and val5 one the last bit.
The result would be this:
1010 0000 0000 1000
I only found out how to the one specific bit but not 'groups'. (shift or bitset)
Does anyone have an idea how to solve this issue?
There are (at least) two basic approaches. One would be to create a struct with some bitfields:
struct bits {
unsigned a : 1;
unsigned b : 7;
unsigned c : 4;
unsigned d : 3;
unsigned e : 1;
};
bits b;
b.a = val1;
b.b = val2;
b.c = val3;
b.d = val4;
b.e = val5;
To get the 16-bit value, you could (for one example) create a union of that struct with a uint16_t. Just one minor problem: the standard doesn't guarantee what order the bit fields will end up in when you look at the 16-bit value. Just for example, you might need to reverse the order I've given above to get the order from most to least significant bits that you really want (but changing compilers might muck things up again).
The other obvious possibility would be to use shifting and masking to put the pieces together into a number:
int16_t result = val1 | (val2 << 1) | (val3 << 8) | (val4 << 12) | (val5 << 15);
For the moment, I've assumed each of the inputs starts out in the correct range (i.e., has a value that can be represented in the chosen number of bits). If there's a possibility that could be wrong, you'd want to mask it to the correct number of bits first. The usual way to do that is something like:
uint16_t result = input & ((1 << num_bits) - 1);
In case you're curious about the math there, it works like this. Lets's assume we want to ensure an input fits in 4 bits. Shifting 1 left 4 bits produces 00010000 (in binary). Subtracting one from that then clears the one bit that's set, and sets all the less significant bits than that, giving 00001111 for our example. That gives us the first least significant bits set. When we do a bit-wise AND between that and the input, any higher bits that were set in the input are cleared in the result.
One of the solutions would be to set a K-bit value starting at the N-th bit of field as:
uint16_t value_mask = ((1<<K)-1) << N; // for K=4 and N=3 will be 00..01111000
field = field & ~value_mask; // zeroing according bits inside the field
field = field | ((value << N) & value_mask); // AND with value_mask is for extra safety
Or, if you can use struct instead of uint16_t, you can use Bit fields and let the compiler to perform all these actions for you.
finalvle = 0;
finalvle = (val1&0x01)<<15;
finalvle += (val2&0x07)<<12;
finalvle += (val3&0x0f)<<8
finalvle += (val4&0xfe)<<1;
finalvle += (val5&0x01);
You can use the bitwise or and shift operators to achieve this.
Use shift << to 'move bytes to the left':
int i = 1; // ...0001
int j = i << 3 // ...1000
You can then use bitwise or | to put it at the right place, (assuming you have all zeros at the bits you are trying to overwrite).
int k = 0; // ...0000
k |= i // ...0001
k |= j // ...1001
Edit: Note that #Inspired's answer also explains with zeroing out a certain area of bits. It overall explains how you would go about implementing it properly.
try this code:
uint16_t shift(uint16_t num, int shift)
{
return num | (int)pow (2, shift);
}
where shift is position of bit that you wanna set
I have a 5 byte data element and I need some help in figuring out how in C++ to set an individual bit of one of these byte; Please see my sample code below:
char m_TxBuf[4];
I would like to set bit 2 to high of byte m_TxBuf[1].
00000 0 00
^ This one
Any support is greatly appreciated;
Thanks!
Bitwise operators in C++.
"...set bit 2..."
Bit endianness.
I would like to set bit 2 to high of byte m_TxBuf[1];
m_TxBuf[1] |= 1 << 2
You can use bitwise-or (|) to set individual bits, and bitwise-and (&) to clear them.
int bitPos = 2; // bit position to set
m_TxBuf[1] |= (1 << bitPos);
m_TxBuf[1] |= 4;
To set a bit, you use bitwise or. The above uses compound assignment, which means the left side is one of the inputs and the output.
Typically we set bits using bitwise operator OR (operator| or operator|= as a shorthand).
Assuming 8-bits to a byte (where the MSB is considered the '7st' bit and the LSB considered the 0th: MSB 0) for simplicity:
char some_char = 0;
some_char |= 1 << 0; // set the 7th bit (least significant bit)
some_char |= 1 << 1; // set the 6th bit
some_char |= 1 << 2; // set the 5th bit
// etc.
We can write a simple function:
void set_bit(char& ch, unsigned int pos)
{
ch |= 1 << pos;
}
We can likewise test bits using operator&.
// If the 5th bit is set...
if (some_char & 1 << 2)
...
You should also consider std::bitset for this purpose which will make your life easier.
Just use std::bitset<40> and then index bits directly.