c++ take half-word from integer variable when displayed in hex - c++

I have an integer
int value = 0x12345678;
I want to take the first half and the second half and place the two halves into two separate integers
e.g.
int value2 = 0x1234;
int value3 = 0x5678;
How would I go about doing this?

Shift the number by 16 bits to the right to get the first half.
int value2 = (value >> 16);
Use bitwise & to get the second half.
int value3 = (value & 0xFFFF);

Note that I changed this to using unsigned (to avoid sign-extension on 32-bit platforms for arbitrary values of value1)
unsigned value1 = 0x12345678;
unsigned value2 = value1 / 0x10000;
unsigned value3 = value1 % 0x10000;
I chose this method -- only caring about the int values here.
If you take care about the representation, you can also use shift operators and masks.

Related

Concatenate Bits from 3 characters, taken from different locations in the bitset

I am trying to concatenate the bits of 3 characters a, b and c into a bitset of 16 bits. The constraints are the following:
Concatenate the last 2 bits of a into newVal1
Concatenate the 8 bits of b into newVal1
Concatenate the first 2 bits of c into newVal1
On paper I am getting: 1111111111110000 same as the result. But I am not sure of the way I am concatenating the bits. First shift left by 14 character a then shift left by 6 character b and finally, since There is no space left for character c then shift right by 2. Is there a better way to do it? It's already confusing for me
#include <iostream>
#include <bitset>
int main() {
int a = 0b11111111 & 0b00000011;
int b = 0b11111111;
int c = 0b11111111 & 0b11000000;
uint16_t newVal1 = (a << 14) + (b << 6) + (c >> 2 );
std::cout << std::bitset<16>(newVal1).to_string() << std::endl;
return 0;
}
First of all you need to consider the signed and unsigned integer problem. With signed integers you can get unexpected sign extensions, adding all ones at the top. And possible overflow will lead to undefined behavior.
So the first thing I would do is to use all unsigned integer values.
Then to make it clear and simple, my suggestion is that you do all the shifting on newVal1 instead, and just do bitwise OR into it:
unsigned a = /* value of a */;
unsigned b = /* value of b */;
unsigned c = /* value of c */
unsigned newVal1 = 0;
newVal1 |= a & 0x02; // Get lowest two bits of a
newVal1 <<= 8; // Make space for the next eight bits
newVal1 |= b & 0xffu; // "Concatenate" eight bits from b
newVal1 <<= 2; // Make space for the next two bits
newVal1 |= (c >> 6) & 0x02; // Get the two "top" bits from c
Now the lowest twelve bits of newVal1 should follow the three rules set up for your assignment. The bits top bits will be all zero.

Increasing hex value with given data

I need to compare given text data with checkSumCalculator method and I try to send the data with command method. I find and changed the code according to my own needs. But I dont understand some parts.
How can 0x00 hex char will be increase with given data? and how/what is the point of comparing check_data with 0xFF? How to extract (check_data & 0xFF) from 0x100 hex? I am very confused.
void Widget::command()
{
std::string txt = "<DONE:8022ff";
unsigned char check_sum = checkSumCalculator(&txt[0], txt.size());
QString reply= QString::fromStdString(txt) + QString("%1>").arg(check_sum, 2, 16,
QChar('0'));
emit finished(replyMessage, true);
}
static unsigned char checkSumCalculator(void *data, int length)
{
unsigned char check_data = 0x00;
for (int i = 0; i < lenght; i++)
check_data+= ((unsigned char*)data)[i];
check_data = (0x100 - (check_data & 0xFF)) & 0xFF;
return check_data;
}
checkSumCalculator starts by adding together all the values of the buffer in data. Because the type of data is unsigned char, this sum is done modulo 0x100 (256), 1 more than the maximum value an unsigned char can handle (0xFF = 255); the value is said to "wrap around" ((unsigned char) (0xFF + 1) = 256) is again 0).
These two lines:
check_data = (0x100 - (check_data & 0xFF)) & 0xFF;
return check_data;
are really more complicated than it's needed. All that would be needed would be:
return -check_data;
That is, at the end it negates the value. Because the arithmetic is modulo 256, this is essentially the same as flipping the bits and adding 1 (-check_data = ~check_data + 1). This is instead implemented in a more convoluted way:
check_data & 0xFF doesn't do much, because it's a bitwise AND with all the possible bits that can be set on an unsigned char. The value is promoted to an unsigned int (due to C's default integer promotions) where all the bits higher than the lower 8 are necessarily 0. So this is the same as (unsigned int)check_data. Ultimately, this promotion has no bearing on the result.
Subtracting from 0x100 is the same as -check_data, as far as the lower 8 bits are concerned (which what we end up caring about).
The final & 0xFF is also redundant because even though the expression was promoted to unsigned int, it will converted as an unsigned char by returning.

Bits shifted by bit shifting operators(<<, >>) in C, C++

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.

How to set specific bits?

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

Arithmetic vs logical shift operation in C++

I have some code that stuffs in parameters of various length (u8, u16, u32) into a u64 with the left shift operator.
Then at various places in the code i need to get back the original parameters from this big bloated parameter.
Just wondering how , in the code, should we ensure that its a logical right shift and not arithmetic one while getting back the original parameters.
So the qestion is are there any #defs or other ways to ensure and check whether the compiler will screw up?
Here's the C++ code:
u32 x , y ,z;
u64 uniqID = 0;
u64 uniqID = (s64) x << 54 |
(s64) y << 52 |
(s64) z << 32 |
uniqID; // the original uniqID value.
And later on while getting the values back :
z= (u32) ((uniqID >> 32 ) & (0x0FFFFF)); //20 bits
y= (u32) ((uniqID >> (52 ) & 0x03)); //2 bits
x= (u32) ((uniqID >> (54) & 0x03F)); //6 bits
The general rule is a logical shift is suitable for unsigned binary numbers, while the arithmetic shift is suitable for signed 2's comp numbers. It will depend on your compiler (gcc etc), not so much the language, but you can assume that the compiler will use a logical shift for unsigned numbers... So if you have an unsigned type one would think that it will be a logical shift.
You can always write your own method to check and do the shifting if you need some portability between compilers. Or you can use in-line asm to do this and avoid any issues (but you would be fixed to a platform).
In short to be 100% correct check your compiler doco.
This looks like C/C++, so just make sure uniqID is an unsigned integer type.
Alternatively, just cast it:
z = (u32) ( ((unsigned long long)uniqID >> (32) & (0x0FFFFF)); //20 bits
y = (u32) ( ((unsigned long long)uniqID >> (52) & 0x03)) ; //2 bits
x = (u32) ( ((unsigned long long)uniqID >> (54) & 0x03F)) ; //6 bits