在C ++中将char转换为int而没有符号位传播

时间:2017-07-18 20:34:23

标签: c++ casting

一个字节的数据存储在' char'成员变量。它应该存储为未签名的字符'相反,但不能改变。我需要通过' int'来检索它。变量,但没有传播符号位。

我的解决方案是这个(UINT和UCHAR是显而易见的类型):

void Foo::get_data( int *val )
{
    if( val )
        *val = (int)(UINT)(UCHAR)m_data;  // 'm_data' is type 'char'
}

这对我来说似乎是最好的解决方案。我可以用

*val = 0xff & (int)m_data;

而不是演员,但这看起来并不可读。哪种选择更好,如果是,为什么?

3 个答案:

答案 0 :(得分:2)

只需写下

*val = (UCHAR)m_data;

由于表达式(UCHAR)m_data具有无符号类型,因此不会传播符号位。

答案 1 :(得分:1)

强制转换是更好的,因为有些编译器(例如clang)实际上会为bitwise和。当然,你只需要一个演员unsigned char

演员也更好地表达了你的意图:数据实际上是你移动到int的unsigned char。因此,即使使用生成相同代码的编译器,我也会更好地调用它。

答案 2 :(得分:1)

此处的转化类型为Integral promotion

当推广到更宽的整数类型时,该值始终为"加宽"使用其符号,以便将符号传播到有符号值的新高位。为避免符号传播,首先将带符号值转换为其对应的无符号类型。

您可以使用明确的*val = static_cast<UCHAR>(m_data)

或者更安全,使用as_unsigned函数作为*val = as_unsigned(m_data)。函数as_unsigned看起来像:

inline unsigned char as_unsigned(char a) { return a; }
inline unsigned char as_unsigned(unsigned char a) { return a; }
inline unsigned char as_unsigned(signed char a) { return a; }
// And so on for the rest of integer types.

使用as_unsigned消除了在维护后显式转换变得不正确的风险,如果m_data变为更宽的整数,它将自动使用as_unsigned的另一个重载,而无需维护者手动更新表达方式。反函数as_signed也很有用。