Implicit type casting

What is type casting?

Converting a variable into an other type of variable is called type casting. There are two types of type casting: implicit type casting and explicit type casting.

Implicitly converting variables

An implicit type casting happens when the value of a variable is converted into an other type automatically, without us asking the compiler to convert it. Implicit conversions are only possible when the conversion between the two types is defined. The conversions between the primitive types are automatically defined.

1
2
3
4
5
6
7
8
9
10
11
#include <iostream> int main() { short num = 90; unsigned int num2 = num; // Implicit type casting. std::cout << num2 << std::endl; // 90 is printed in the console. return 0; }

Type casting may however, in some cases, cause precision loss. It can be the case when we convert a floating point number into an integer type, because the decimals will be removed.

1
2
3
4
5
6
7
8
9
10
11
#include <iostream> int main() { float num = 56.678; int num2 = num; // Implicit type casting std::cout << num2 << std::endl; // 56 is printed in the console. return 0; }

When a variable of signed type, which hold a negative value, is converted into an unsigned integer type, the result is the number of values the unsigned integer type can hold added with the value of the signed variable.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream> int main() { int num = -5000; unsigned int num2 = num; // Implicit type casting /* If unsigned int weights 32 bits, then the number of values it can hold is: 4 294 967 296 Added with -5000, the result is: 4 294 962 296 */ std::cout << num2 << std::endl; // 4294962296 is printed in the console. return 0; }

When a smaller primitive type is converted into a bigger type of the same category, the conversion is called a promotion and it is safe as it never causes precision or data loss. However, the opposite, bigger type to smaller, may cause data loss or precision loss. If a bigger integer type is converted into a smaller integer type, data can be lost if the value represented by the variable of bigger size is too big to be represented by the smaller type. Since variables of floating point primitive type, in most cases, only approximate the value of numbers, converting a bigger floating point type into a smaller one may either cause precision or data loss. Note, however, that variables of floating point type can represent very huge numbers, so it is usually unlikely that a variable of floating point number type holds a number that a smaller floating point can not hold. Therefore, even though precision loss is very frequent while converting bigger floating point types to smaller ones, data loss is not.

In the example below, the method setprecision(streamsize p) of the object std::cout is used. The reason is that by default, when there is a good amount of them, std::cout will not display all the digits after the decimal of floating point numbers it prints. So in the code below, that method is used to increase the number of digit displayed so we can see, in the console, the whole content of the floating point variables.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream> int main() { double n = 123456789.123456789; std::cout.precision(18); // Display up to 18 digits std::cout << n << std::endl; // 123456789.123456791 is printed in the console. float n2 = n; std::cout << n2 << std::endl; // 123456792 is displayed in the console. n = 12345.123456789; std::cout << n << std::endl; // 12345.1234567890006 is displayed in the console. n2 = n; std::cout << n2 << std::endl; // 12345.123046875 is displayed in the console. return 0; }

Note that the result of the example above may vary depending on the size of the types float and double, defined by your compiler. As you can see, the precision loss in the example above is huge. The reason is that the compiler used define the float type with 32 bits and the double type with 64 bits.