问题
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 int
s 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 int
s, casting back to a char
only when the assignment is done. Since the temporary values are int
s, 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