Type conversion and casting


1.1.   TYPE CONVERSION AND CASTING

Calculations in C++ can be carried out only between values of the same type. When you write an expression involving variables or constants of different types, for each operation to be performed, the compiler has to arrange to convert the type of one of the operands to match that of the other. This process is called implicit type conversion . For example, if you want to add a double value to a value of an integer type, the integer value is fi rst converted to double , after which the addition is carried out. Of course, the variable that contains the value to be converted is, itself, not changed. The compiler will store the converted value in a temporary memory location, which will be discarded when the calculation is fi nished. There are rules that govern the selection of the operand to be converted in any operation. Any expression to be calculated breaks down into a series of operations between two operands. For example, the expression 2*3 - 4+5 amounts to the series 2*3 resulting in 6 , 6 - 4 resulting in 2 , and fi nally 2+5 resulting in 7 . Thus, the rules for converting the type of operands where necessary needto be defi ned only in terms of decisions about pairs of operands. So, for any pair of operands of different types, the compiler decides which operand to convert to the other considering types to be in the following rank from high to low:
1 long double
2 double
3 float
4 unsigned long long
5 long long
6 unsigned long
7 long
8 unsigned int
9 int


Thus, if you have an operation where the operands are of type long long and type unsigned int , the latter will be converted to type long long . Any operand of type char , signed char , unsigned char , short , or unsigned short is at least converted to type int before an operation. Implicit type conversions can produce some unexpected results. For example, consider the following statements:
unsigned int a(10u);
signed int b(20);
std::cout < < a - b < < std::endl;
You might expect this code fragment to output the value  10, but it doesn ’ t. It outputs the value 4294967286. This is because the value of b is converted to unsigned int to match the type of a , and the subtraction operation results in an unsigned integer value. This implies that if you have to write integer operations that apply to operands of different types, you should not rely on implicit type conversion to produce the result you want unless you are quite certain it will do so.

1.1.1.                 Type Conversion in Assignments

As you saw in example Ex2_05.cpp earlier in this chapter, you can cause an implicit type conversion by writing an expression on the right - hand side of an assignment that is of a different type from the variable on the left - hand side. This can cause values to be changed and information to be lost. For instance, if you assign an expression that results in a float or double value to a variable of type int or a long , the fractional part of the float or double result will be lost, and just the integer part will be stored. (You may lose even more information if the value of your floating - point result exceeds the range of values available for the integer type concerned.) For example, after executing the following code fragment,
int number = 0;
float decimal = 2.5f;
number = decimal;
the value of number will be 2. Note the f at the end of the constant 2.5f. This indicates to the compiler that this constant is single - precision floating - point. Without the f , the default would have been type double . Any constant containing a decimal point is floating - point. If you don’t want it to be double - precision, you need to append the f . A capital letter F would do the job just as well.

1.1.2.                 Explicit Type Conversion

With mixed expressions involving the basic types, your compiler automatically arranges casting where necessary, but you can also force a conversion from one type to another by using an explicit type conversion, which is also referred to as a cast . To cast the value of an expression to a given type, you write the cast in the form:
static_cast < the_type_to_convert_to > ( expression )
The keyword static_cast reflects the fact that the cast is checked statically — that is, when your program is compiled. No further checks are made when you execute the program to see if this cast is safe to apply. Later, when you get to deal with classes, you will meet dynamic_cast , where the conversion is checked dynamically — that is, when the program is executing. There are also two other kinds of cast — const_cast for removing the const - ness of an expression, and reinterpret_cast , which is an unconditional cast — but I ’ ll say no more about these here.
The effect of the static_cast operation is to convert the value that results from evaluating expression to the type that you specify between the angled brackets. The expression can be anything from a single variable to a complex expression involving lots of nested parentheses
Here’s a specifi c example of the use of static_cast < > () :
double value1 = 10.5;
double value2 = 15.5;
int whole_number = static_cast < int > (value1) + static_cast < int > (value2);
The initializing value for the variable whole_number is the sum of the integral parts of value1 and value2 , so they are each explicitly cast to type int . The variable whole_number will therefore have the initial value 25. The casts do not affect the values stored in value1 and value2, which will remain as 10.5 and 15.5, respectively. The values 10 and 15 produced by the casts are just stored temporarily for use in the calculation and then discarded. Although both casts cause a loss of information in the calculation, the compiler will always assume that you know what you are doing when you specify a cast explicitly
strips_per_roll = static_cast < int > (rollLength / height); //Get number of strips
// in a roll
You can write an explicit cast for a numerical value to any numeric type, but you should be conscious of the possibility of losing information. If you cast a value of type float or double to type long, for example, you will lose the fractional part of the value when it is converted, so if the value started out as less than 1.0, the result will be 0. If you cast a value of type double to type float, you will lose accuracy because a float variable has only 7 digits precision, whereas double variables maintain 15. Even casting between integer types provides the potential for losing data, depending on the values involved. For example, the value of an integer of type long long can exceed the maximum that you can store in a variable of type int , so casting from a long long value to an int may lose information.
In general, you should avoid casting as far as possible. If you fi nd that you need a lot of casts in your program, the overall design of your program may well be at fault. You need to look at the structure of the program and the ways in which you have chosen data types to see whether you can eliminate, or at least reduce, the number of casts in your program.

1.1.3.                 Old - Style Casts

Prior to the introduction of static_cast < > () (and the other casts: const_cast < > () , dynamic_ cast < > () , and reinterpret_cast < > () , which I’ll discuss later in the book) into C++, an explicit cast of the result of an expression to another type was written as: (the_type_to_convert_to) expression The result of expression is cast to the type between the parentheses. For example, the statement to calculate strips_per_roll in the previous example could be written: strips_per_roll = (int)(rollLength / height); //Get number of strips in a roll Essentially, there are four different kinds of casts, and the old - style casting syntax covers them all. Because of this, code using the old - style casts is more error - prone — it is not always clear what you intended, and you may not get the result you expected. Although you will still see the old style of casting used extensively (it ’ s still part of the language and you will see it in MFC code for historical reasons), I strongly recommend that you stick to using only the new casts in your code.
Share on Google Plus