使用按位将int值存储在int上,并在没有强制转换的情况下保存值符号值时正确无误
问题描述:
我有一些要存储在signed 32 bit integer
上的signed 8 bit
值。使用按位将int值存储在int上,并在没有强制转换的情况下保存值符号值时正确无误
我这样做,移动使用逐移值左:
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;
现在,让我们说,我想回去value1
从merged_value
我是这样做的:
const auto back_value1 = (merged_value >> 24) & 0x000000FF;
该作品伟大的只要value1
是一个正数,但如果该值是负数,返回值将是错误的。
例如,如果value1
是-80
,然后back_value1
将176
,这是因为最显著位(正或负位)是在比特位置7
,而不是在31
(因为back_value1
是int32_t
)。
现在,我知道我只需要对char
进行演员制作back_value1
,我将获得-80
值。但是我想要的是一个按位操作,它会给我正确的值-80
到back_value1
当back_value1
是int32_t
而没有投到char
。
感谢
编辑:
尼尔·巴特沃思问,我在这里,而不是在一个在线IDE张贴整个代码,所以这里是:
#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;
}
答
答案是:为了得到与原始int8_t
相同符号的int32_t
的值,您需要:
投回int8_t
:
const auto back_value1 = int32_t(int8_t((merged_value >> 24) & 0xFF));
,或者确保你所需要的字节在int32_t
的左端前,右移:
const auto back_value1 = merged_value /* << 0 */ >> 24;
const auto back_value2 = merged_value <<8>> 24;
不用说了,我不推荐后者。
“我想存储在一个有符号的32位整数。” - 为什么要签名? –
它不是,也可以是一个无符号的32位,因为它最终只是一个容器,我只是把签名变得更具体,但我想它只是造成了混淆。 –
这看起来像另一个例子,使用正确的显式类型而不是'auto'会解决问题,或者至少简化它。 –