一个字节的数据存储在' 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;
而不是演员,但这看起来并不可读。哪种选择更好,如果是,为什么?
答案 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
也很有用。