C++ Differences between signed int and unsigned int type
The main difference between signed and unsigned int data types in C++ is that signed int can represent both +ve and -ve value while unsigned int can represent only +ve value. A simple code is given below
unsigned int usi=-90 ; cout<< si << endl /*prints -90 */ << usi ; //prints some +ve value not -90
How does signed type support -ve value and unsigned type does not
The method that ‘signed int’ and ‘int’ type employ to support negative value is simple. In ‘int’ or ‘signed int’ type the leftmost bit is preserved for storing either 1 or 0 bit. These bits hold certain significance in terms of the sign the value will have. If the preserve bit is marked 1 then the value will have -ve sign but if the bit is marked 0 then the sign is +ve.
These bits are deduced automatically by the compiler when the value is assigned to the variable. If the value assigned is a negative value then the compiler knows that the leftmost bit should be 1, so it marks the leftmost bit as 1, whereas if the value is +ve the compiler marks the leftmost bit as 0.
This method is rather simple to implement but it has a side effect. Since the leftmost bit is preserved for either 1 or 0 bit, there are only 31 bits(size of int type is 4 bytes,(4*8-1)=31) left to represent the absolute value. The integer zero(0) is considered as +ve value so the maximum +ve value a signed int type can represent is ( 231-1) which is 2147483647. And the smallest -ve value it can represent is -231, which is -2147483648.
Unlike the signed int the unsigned int type does not make any special allocation of the leftmost bit for +ve or -ve sign. This means they have a total of 32 bits at their disposal to represent the integer value. This also means it can represent only +ve values but larger in range than the int or signed int type.
The range of values it can represent varies from 0 to (232 – 1) (4294967295). A simple program is given below to show that the unsigned int type does not support -ve integer value.
#include <iostream> using namespace std ; int main( ) { signed int si=-90; unsigned usi=-900; cout<< si << endl; cout << usi << endl ; //Negative value is not the output here cin.get( ) ; return 0 ; }
Output,
-90
4294966396
As you can see, when a negative integer is assigned to an unsigned type variable the output is still +ve value. This clearly shows that unsigned type cannot represent -ve value.
The reason why the output of the unsigned int variable assigned the value -900 is 4294966396 will be discussed in another post.
Uses of int and unsigned int
We know the differences between signed int and unsigned int type(which is given above) now, let’s see their uses.
Signed int can represent both +ve and -ve value so we can use it in our program which requires both +ve and -ve value. But, if our program needs only +ve value we can use the unsigned int type. However, it is recommended that we use int or signed int type instead of unsigned int type because we are not always sure that our program will need only +ve values.
Use unsigned type if you need an integer value for the bitwise operation. Using signed type for bitwise operation can sometimes give an unexpected output. Consider the program below.
signed short si1=65532 , si2=4 , sresult1 ; unsigned short usresult1 ; usresult1=si1 | si2 ; sresult1=si1 | si2 ; cout<< usresult << endl << sresult << endl ;
Before we examine the output of the program let’s perform a bitwise ‘or‘ operation between si1 and si2, and see for ourselves what value can be expected. The bit format of si1(65532)=1111111111111100 and si2=0000000000000100. The bitwise ‘or’ operation is shown below.
We expect the output to be 65532 for both the values. However, it is not and in case of ‘signed int’ variable, the output is -4. This unexpected output value is due to the fact that since ‘unsigned’ type cannot represent the value 65532, a bitwise complement is performed on the value 65532 and outputs the value -4.
Such uncertainty in the resultant value of the bitwise operation when the variable is signed type can lead to some disastrous result if you are not careful. To simplify things and prevent our program from behaving differently it is better that we always use unsigned type in every bitwise operation.