Converting char to int without sign bit propagation in C++

做~自己de王妃 提交于 2019-12-24 19:41:23

问题


A byte of data is being stored in a 'char' member variable. It should probably be stored as an 'unsigned char' instead, but that can't be changed. I need to retrieve it through an 'int' variable, but without propagating the sign bit.

My solution was this (UINT and UCHAR are the obvious types):

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

This seemed the best solution to me. I could use

*val = 0xff & (int)m_data;

instead of the casting, but this doesn't seem as readable. Which alternative is better, if either, and why?


回答1:


Just write

*val = (UCHAR)m_data;

As now the expression (UCHAR)m_data has an unsigned type neither sign bit will be propagated.




回答2:


The cast is better because some compilers (eg. clang) actually generate extra code for the bitwise and. Of course, you only need the one cast to unsigned char.

The cast also expresses your intent better: the data is actually an unsigned char that you move to an int. So I would call it better even with compilers which generate the same code.




回答3:


The type of conversion here is Integral promotion.

When promoting to a wider integer type the value is always "widened" using its signedness, so that the sign is propagated to the new high order bits for signed values. To avoid the sign propagation convert a signed value to its corresponding unsigned type first.

You can do that with an explicit *val = static_cast<UCHAR>(m_data).


Or, safer, using as_unsigned function as *val = as_unsigned(m_data). Function as_unsigned looks like:

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.

Using as_unsigned eliminates the risk of that explicit cast becoming incorrect after maintenance, should m_data become a wider integer it will use another overload of as_unsigned automatically without requiring the maintainer to manually update the expression. The inverse function as_signed is also useful.



来源:https://stackoverflow.com/questions/45176562/converting-char-to-int-without-sign-bit-propagation-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!