Why is int i = 1<<31 == -2147483648 instead of 2147483648? [duplicate] - c++

This question already has answers here:
Why is the maximum value of an unsigned n-bit integer 2ⁿ-1 and not 2ⁿ?
(12 answers)
Closed 5 years ago.
I was trying to understand the bitwise operation and according to me integer contains 32 bit and from LSB 0th position to MSB 31st position so if I set left shift 1 to 31 place I think I should get 2^31 and the binary representation of it would be 10000000 00000000 00000000 00000000 so why in am getting the result as negative ? and please correct me if I am wrong.
#include<bits/stdc++.h>
using namespace std;
int main(){
int i=1<<31;
cout<<i;
return 0;
}

Integer is a 32bit data type and its most significant bit stands for the sign. (That is the 32nd bit)
Therefore you're getting a negative value

C++ does not specify the behaviour of programs that include 1<<31.
On a different platform you may get a different answer, or a compilation error, or a program that formats your drive, or any other behaviour.

Related

Why main function cannot return a negative number?

This might be a really simple question for some, but I'm new to C++ and hope someone can answer this for me.
I'm using this online C++ compiler. Here's the simple code I'm running in it:
int main()
{
int x = 1- 2;
std::cout << x << std::endl;
return x;
}
The output is:
-1
...Program finished with exit code 255
Press ENTER to exit console.
That really ponders me. Why would the main() function return 255 when the value of x is -1?
Doesn't main() return an int (not an unsigned int), so it should be able to return a negative number, right?
How does -1 get converted to 255? Something to do with an 8-bit variable? But isn't the int type 16-bit?
This is not related to C language really. The operating system, or possibly just the C runtime (the small piece of the code which sets up things for your C program and actually calls your main function) limits exit code of the program to unsigned 8 bit number.
Very nearly all systems today use two's complement representation for negative numbers, and then bit pattern for -1 is having all bits of the number to be 1. Doesn't matter how many bits, they are all set when value is -1.
The simplest way to convert an int to 8 bit number is to just take 8 lowest bits (which are now all 1 as per above), so you end up with binary number:
11111111
If interpreted as unsigned, then in decimal value of this happens to be 255 (as signed 8 bits it is still -1), which you can check with any calculator which supports binary (such as Windows 10 Calculator app when you switch it to Programmer mode).
Looking at this from the opposite direction: When trying to understand funny numbers related to computers or programming, it is often useful to convert them to binary. If you convert 255 to binary, you get 11111111, and then if you know binary numbers, you should realize this is -1 if interpreted as signed 8 bit number.

Web compiler outputting weird results [duplicate]

This question already has answers here:
What is “two's complement”?
(24 answers)
Closed 5 years ago.
Take a look at this compiler:
https://ideone.com/Y09Z0N
The code is very simple:
cout << ~5;
And this outputs -6
Now I'm no C++ guru, but somehow I remember that the ~ operator should flip a numbers bits, and since 5 is 101, I would expect to get 010, which is 2, or more precisely 5 is 0000......101 and I should get 1111...010 which should be a really big negative number and not 6 (110). The question is: am I wrong about the operator or am I missing something?
Negative integers are typically represented in two's complement.
This allows basic operations such as addition and subtraction to work with negative numbers in the exactly the same way as positive ones. In that form, negatives are represented as:
00000000 = 0
11111111 = -1
11111110 = -2
11111101 = -3
11111100 = -4
11111011 = -5
11111010 = -6
So indeed -6 = ~5
This is actually a subtle thing about two's complement.
I will write your numbers in base 16, at the size of the variable (I assume 32 bits, but you can alter the answer for other sizes).
5 is 0x00000005. ~5 is its negation, 0xFFFFFFFA. Add 5 to that, and you see ~5 + 5 is 0xFFFFFFFF. Add one more and you get 0x00000000, or 0, due to overflow.
Two's complement representation has made it so that incrementing past 0x7FFFFFFF (or 2147483647) is the actual overflow (and 0x80000000 is -2147483648), and simply the increment from -1 to 0 has been made not to cause an overflow.
You may read more about two's complement representation and also ask for more info from me if you wish.

Why is the binary equivalent calculation getting incorrect?

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?
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.
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 1s. 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).
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(like int) 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)

what value will be printed out if it is out of range in C++

I am a rookie in C++ and I have got a question here.
I use an int to print the first 100 power of 2. I know that the outcome will be out of range of an int variable. I am just curious since the result given by the program is 0. How did 0 come out?
Thanks in advance!
My code is as followed:
#include<iostream>
using namespace std;
void main()
{
int a=1;
unsigned int b=1;
for (int i=1;i<=100;i++)
{
a=2*a;
b=2*b;
}
cout<<"the first 1oo powers of 2 is (using an signed int): "<<a<<endl;
cout<<"the first 1oo powers of 2 is (using an unsigned int): "<<b<<endl;
//The fix
cout<<"Enter a Char to Exit."<<endl;
char theFix;
cin>>theFix;
}
Multiplying an unsigned integer or a positive signed integer by 2 is like shifting left by 1, while a 0 bit will be shifted in from the right. After 32 iterations (assuming 32 bit integers), the entire value will be all 0 bits. After that, shifting 0 left will not change the outcome anymore.
Since, you're new to C++, you might not know how the computer stores information. Eventually, all integers are broken down into 32-bit binary numbers (a bunch of 1's and 0's).
a = a * 2; // multiplication
a << 1; // left shift
These two instructions are actually synonymous due to the nature of binary numbers.
For instance, 0....000010 in binary notation == 2 in decimal notation.
So,
2 * 2 = 4 = 0....000100
4 * 2 = 8 = 0....001000
8 * 2 = 16 = 0....010000
and so on...
Since the bit count is capped at 32 for integers, you'll get a huge number 2^32 == 1000....000. When you multiply by 2 again, the number is shifted left again and you end up with 000...000000 = 0.
All further multiplications of 0 = zero, so that's where your final result came from.
EDIT: Would just like to point out that this is one of the only situations where this exact result would occur. If you were to try using the number 3, for example, you would see the expected integer overflow behavior.

Can someone please explain this line of code to me? [duplicate]

This question already has answers here:
<< operator in C++?
(3 answers)
Closed 9 years ago.
I'm reading values from an accelerometer and saving them in a buffer called 'values'. Each accelerometer reading is 10 bits long, but the values are read in as bytes, so eah accelerometer reading is actually two bytes or two values in the 'values' buffer. This is sample code on how to combine those two bytes to get the one value:
x = ((int)values[1]<<8)|(int)values[0];
I get that I'm combining values[1] and values[2] and I'm pretty sure the (int) part is type casting those parts as integers (although I'm not sure why). The parts that have me really confused are <<8 and the vertical bar |. What are these two parts doing?
Thanks for any explanation and help you can give!
It's a bitmask.
You are left shifting (<<) the value in values[1] by 8 bit-positions. and then ORing (|) it to the value in values[0].
Please take some values and try to work through them. You will understand it better.
Here's a link for more reading and bit-manipulation examples.
This line of code combines two char into a int in a way that first char is moved 8 bits.
For example, value[0] = 5, value[1] = 1, then the read in value should be, 128 + 5 = 133. Because the high byte 1 means 128. Another way to look at it is:
x = ((int)values[1]<<8) + (int)values[0];
Replace or with +, it will be more readable. Hope this helps.
Take for example a 10-bit reading of 0101010111 in binary.
The lower 8 bits go to values[0] = 01010111 in binary (= 87 decimal).
The higher 2 bits go to values[1] = 01.
To recover the original 10-bit number from values:
(int)values[1] << 8 --> 01 << 8 --> 0100000000
values[1] is converted to a int (typically 32 bits) and then shifted left << 8 bits.
((int)values[1]<<8) | (int)values[0] --> 0100000000 | 01010111
or in vertical notation to express a bitwise-or:
0100000000
| 01010111
------------
0101010111
QED
The << operator shifts the bits in the second byte left by 8 bits so for example 0000000011111111 becomes 1111111100000000. The | is the binary "or" operator that combines the two bits in every position making it 1 if either bit or both bits are 1.
You have 2 bytes (1 byte = 8 bits) and you are trying to read in a 10 bit value, which is why you need 2 bytes instead of just using 1. When you are reading in the value you need to cast the 2 bytes to int so you can treat them like and integer value, but there is an issue, if value[1] is 3 (00000011) and the next byte value[0] is 227 (11100011) you can get a proper reading if you add them so you need to bit shift value[1] left by 8.
When you bit shift a unsigned char/char/byte by 8 you end up with 0, so you need to cast both value[1] and value[0] to an int so when you do the bit shift you end up with 768 (00000011 00000000) now you | that with value [0] and you end up with
(00000011 00000000 | 00000000 11100011) = (00000011 11100011) = 995
note I am only using 16bit ints so the example isn't full of a bunch of 0s.
If you have access to a programming calculator it can help you understand why you need to cast these byte values to ints, it can also just help you with casting in general. I would sugest playing around with the windows Calculator app for a bit if you have access to it. In order to get it into the programmer view go to view->programmer.