使用按位将int值存储在int上,并在没有强制转换的情况下保存值符号值时正确无误

使用按位将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; 

现在,让我们说,我想回去value1merged_value我是这样做的:

const auto back_value1 = (merged_value >> 24) & 0x000000FF; 

该作品伟大的只要value1是一个正数,但如果该值是负数,返回值将是错误的。

例如,如果value1-80,然后back_value1176,这是因为最显著位(正或负位)是在比特位置7,而不是在31(因为back_value1int32_t)。

现在,我知道我只需要对char进行演员制作back_value1,我将获得-80值。但是我想要的是一个按位操作,它会给我正确的值-80back_value1back_value1int32_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; 
} 
+1

“我想存储在一个有符号的32位整数。” - 为什么要签名? –

+0

它不是,也可以是一个无符号的32位,因为它最终只是一个容器,我只是把签名变得更具体,但我想它只是造成了混淆。 –

+5

这看起来像另一个例子,使用正确的显式类型而不是'auto'会解决问题,或者至少简化它。 –

答案是:为了得到与原始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; 

不用说了,我不推荐后者。