Bitshifting in C++ producing the wrong answer

冷暖自知 提交于 2019-12-07 04:56:00

问题


I tried running the following code code:

char c = (2 << 7) >> 7

which should return 0 because 2 has this binary representation as a char:

0 0 0 0 0 0 1 0

After 7 shifts left, we get

0 0 0 0 0 0 0 0

Then, after seven shifts right, we get

0 0 0 0 0 0 0 0

However, I'm getting the result as 2, not 0.

The compiler says that 2 << 7 is 256, but it's a char and so it shouldn't be 256.

I understand that the 2 << 7 will be calculated as ints and the answer will be put into c so 256 >> 7 is 2.

I tried to cast 2 to char (ex: (char)2>>7) but it doesn't work either.

I'm trying to extract each bit from the char, so I wrote this code:

char c = 0x02;
for(int i=0;i<7;i++)
{
    char current = (c<<i)>>7;
}

How can I get each bit? What's wrong with my way?


回答1:


The result of an arithmetic shift operation with one operand being an int in C++ is always an int. Therefore, when you write

current = (c << i) >> 7;

C++ will interpret (c << i) and (c << i) >> 7 as ints, casting back to a char only when the assignment is done. Since the temporary values are ints, no overflow occurs and the result should come out to the integer result casted to a char.

Hope this helps!




回答2:


To get each bit, you could write:

(c >> i) & 0x01

Advantage: It works for any integer type.




回答3:


According to 5.8 [expr.shift] paragraph 1:

... The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand. ...

This for a left argument of type char together with the rules on integer promotion (4.5 [conv.prom]) says that the result is int. Of course, an int can hold the result of 2 << 7. You can easily verify this behavior, too:

#include <iostream>

void print(char c) { std::cout << "char=" << int(c) << "\n"; }
void print(int i) { std::cout << "int=" << i << "\n"; }

int main()
{
    print(2 << 7);
}

The most simple approach to get the bits of a value is to use a std::bitset<N> with N being the digits of the corresponding unsigned type, e.g.:

char c('a');
std::bitset<std::numeric_limits<unsigned char>::digits> bits(c);

If you want to get bits yourself you'd mask the bits using its unsigned counterpart of the integer type, e.g.:

template <typename T>
void get_bits(T val)
{
    typedef typename std::make_unsigned<T>::type U;
    U value(val);
    for (std::size_t s(std::numeric_limits<U>::digits); s-- != 0; ) {
        std::cout << bool(value & (1u << s));
    }
    std::cout << '\n';
}


来源:https://stackoverflow.com/questions/24100576/bitshifting-in-c-producing-the-wrong-answer

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