I have some signed 8 bit
values that I want to store on a signed 32 bit integer
.
I do that moving the values using bitwise shift left:
const auto value1 = char{90};
const auto value2 = char{80};
const auto value3 = char{70};
const auto value4 = char{60};
auto merged_value = int32_t{0};
merged_value |= (value1 & 0x000000FF) << 24;
merged_value |= (value1 & 0x000000FF) << 16;
merged_value |= (value1 & 0x000000FF) << 8;
merged_value |= value1 & 0x000000FF;
Now, let's say I want to get back value1
from merged_value
I will do that like this:
const auto back_value1 = (merged_value >> 24) & 0x000000FF;
This works great as long as value1
is a positive number, but if the value is negative, the return value will be wrong.
For example, if value1
is -80
, then back_value1
will be 176
, that's because the most significant bit (the positive or negative bit) is in bit position 7
and not in 31
(since back_value1
is an int32_t
).
Now, I know that I just need to do a cast to char
on back_value1
and I will get the -80
value back. But what I want is a bitwise operation(s) that will give me the correct value -80
to back_value1
when back_value1
is an int32_t
and without a cast to char
.
Thanks
Edit:
Neil Butterworth asked that I post the entire code here instead of on an online IDE, so here it is:
#include <iostream>
#include <bitset>
int main()
{
const auto value = char{-80};
std::cout << "value: " << (int)value << std::endl;
std::cout << "value bits: " << std::bitset<32>(value) << std::endl;
auto merged_value = uint32_t{0};
merged_value |= (value & 0x000000FF) << 24;
const auto back_value = int32_t(merged_value >> 24) & 0xFF;
std::cout << "value: " << back_value << std::endl;
std::cout << "back_value bits: " << std::bitset<32>(back_value) << std::endl;
}
The answer is that to get the value back as an int32_t
with the same sign as the original int8_t
, you need to either:
cast back to a int8_t
:
const auto back_value1 = int32_t(int8_t((merged_value >> 24) & 0xFF));
or make sure the byte you need is at the left end of the int32_t
before right shifting:
const auto back_value1 = merged_value /* << 0 */ >> 24;
const auto back_value2 = merged_value << 8 >> 24;
Needless to say, I don't recommend the latter.
User contributions licensed under CC BY-SA 3.0