Reputation:
I wrote the following program to output the binary equivalent of a integer taking(I checked that int on my system is of 4 bytes) it is of 4 bytes. But the output doesn't come the right. The code is:
#include<iostream>
#include<iomanip>
using namespace std;
void printBinary(int k){
for(int i = 0; i <= 31; i++){
if(k & ((1 << 31) >> i))
cout << "1";
else
cout << "0";
}
}
int main(){
printBinary(12);
}
Where am I getting it wrong?
Upvotes: 18
Views: 1597
Reputation: 122453
The problem is in 1<<31
. Because 231 cannot be represented with a 32-bit signed integer (range −231 to 231 − 1), the result is undefined [1].
The fix is easy: 1U<<31
.
[1]: The behavior is implementation-defined since C++14.
Upvotes: 29
Reputation: 726839
This expression is incorrect:
if(k & ((1<<31)>>i))
int
is a signed type, so when you shift 1
31 times, it becomes the sign bit on your system. After that, shifting the result right i
times sign-extends the number, meaning that the top bits remain 1
s. You end up with a sequence that looks like this:
80000000 // 10000...00
C0000000 // 11000...00
E0000000 // 11100...00
F0000000 // 11110...00
F8000000
FC000000
...
FFFFFFF8
FFFFFFFC
FFFFFFFE // 11111..10
FFFFFFFF // 11111..11
To fix this, replace the expression with 1 & (k>>(31-i))
. This way you would avoid undefined behavior* resulting from shifting 1
to the sign bit position.
* C++14 changed the definition so that shifting 1
31 times to the left in a 32-bit int
is no longer undefined (Thanks, Matt McNabb, for pointing this out).
Upvotes: 8
Reputation: 6467
A typical internal memory representation of a signed integer value looks like:
The most significant bit (first from the right) is the sign bit and in
signed numbers
(likeint
) it represents whether the number is negative or not. When you shift additional bits sign extension is performed to preserve the number's sign. This is done by appending digits to the most significant side of the number.(following a procedure dependent on the particular signed number representation used).
In unsigned numbers the first bit from the right is just the MSB of the represented number, thus when you shift additional bits no sign extension is performed.
Note: the enumeration of the bits starts from 0, so 1 << 31
replaces your sign bit and after that every bit shift operation to the left >>
results in sign extension. (as pointed out by @dasblinkenlight)
So, the simple solution to your problem is to make the number unsigned (this is what U
does in 1U << 31
) before you start the bit manipulation. (as pointed out by @Yu Hao)
For further reading see signed number representations and two's complement.(as it's the most common)
Upvotes: 4