C++ Programming/Programming Languages/C++/Code/Statements/Variables/Type Casting

Type Conversion
Type conversion (often a result of type casting) refers to changing an entity of one data type, expression, function argument, or return value into another. This is done to take advantage of certain features of type hierarchies. For instance, values from a more limited set, such as integers, can be stored in a more compact format and later converted to a different format enabling operations not previously possible, such as division with several decimal places' worth of accuracy. In the object-oriented programming paradigm, type conversion allows programs also to treat objects of one type as one of another. One must do it carefully as type casting can lead to loss of data.

Automatic type conversion
Automatic type conversion (or standard conversion) happens whenever the compiler expects data of a particular type, but the data is given as a different type, leading to an automatic conversion by the compiler without an explicit indication by the programmer.

When an expression requires a given type that cannot be obtained through an implicit conversion or if more than one standard conversion creates an ambiguous situation, the programmer must explicitly specify the target type of the conversion. If the conversion is impossible it will result in an error or warning at compile time. Warnings may vary depending on the compiler used or compiler options.

This type of conversion is useful and relied upon to perform integral promotions, integral conversions, floating point conversions, floating-integral conversions, arithmetic conversions, pointer conversions.

In the example above, in the first case an expression of type float is given and automatically interpreted as an integer. In the second case (more subtle), an integer is given and automatically interpreted as a float.

There are two types of automatic type conversions between numeric types: promotion and conversion. Numeric promotion causes a simple type conversion whenever a value is used, while more complex numeric conversions can take place if the context of the expression requires it.


 * Any automatic type conversion is an implicit conversion if not done explicitly in the source code.

Automatic type conversions (implicit conversions) can also occur in the implicit "decay" from an array to a corresponding pointer type based or as a user defined behavior. We will cover that after we introduce classes (user defined types) as the automatic type conversions of references (derived class reference to base class reference) and pointer-to-member (from pointing to member of a base class to pointing to member of a derived class).

Promotion
A numeric promotion is the conversion of a value to a type with a wider range that happens whenever a value of a narrower type is used. Values of integral types narrower than  (,  ,  ,   and  ) will be promoted to   if possible, or   if   can't represent all the values of the source type. Values of  type will also be converted to , and in particular   will get promoted to 1 and   to 0.

In the code above, the values of  and   are both of type   and could be added and assigned as such. However, in C++ they will each be promoted to  before being added, and the result converted back to   afterwards. The reason for this is that the  type is designed to be the most natural integer representation on the machine architecture, so requiring that the compiler do its calculations with smaller types may cause an unnecessary performance hit.

Since the C++ standard guarantees only the minimum sizes of the data types, the sizes of the types commonly vary between one architecture and another (and may even vary between one compiler and another). This is the reason why the compiler is allowed the flexibility to promote to  or   as necessary.

Promotion works in a similar way on floating-point values: a  value will be promoted to a   value, leaving the value unchanged.

Since promotion happens in cases where the expression does not require type conversion in order to be compiled, it can cause unexpected effects, for example in overload resolution:

Since  is a , you might expect that the expression   would also be a  , but in fact   is promoted to  , and the   overload is selected.

Numeric conversion
After any numeric promotion has been applied, the value can then be converted to another numeric type if required, subject to various constraints.

A value of any integer type can be converted to any other integer type, and a value of an enumeration type can be converted to an integer type. This only gets complicated when overflow is possible, as in the case where you convert from a larger type to a smaller type. In the case of conversion to an unsigned type, overflow works in a nice predictable way: the result is the smallest unsigned integer congruent to the value being converted (modulo $$2^n$$, where $$n$$ is the number of bits in the destination type).

When converting to a signed integer type where overflow is possible, the result of the conversion depends on the compiler. Most modern compilers will generate a warning if a conversion occurs where overflow could happen. Should the loss of information be intended, the programmer may do explicit type casting to suppress the warning; bit masking may be a superior alternative.

Floating-point types can be converted between each other, but are even more prone to platform-dependence. If the value being converted can be represented exactly in the new type then the exact conversion will happen. Otherwise, if there are two values possible in the destination type and the source value lies between them, then one of the two values will be chosen. In all other cases the result is implementation-defined.

Floating-point types can be converted to integer types, with the fractional part being discarded.

A value of an integer type can be converted to a floating point type. The result is exact if possible, otherwise it is the next lowest or next highest representable value (depending on the compiler).

Explicit type conversion (casting)
Explicit type conversion (casting) is the use of direct and specific notation in the source code to request a conversion or to specify a member from an overloaded class. There are cases where no automatic type conversion can occur or where the compiler is unsure about what type to convert to, those cases require explicit instructions from the programmer or will result in error.

Specific type casts
The C++ language introduces several new casting operators to address the shortcomings of the old C-style casts such as a clearer syntax, improved semantics and type-safe conversions. All these casting operators share a similar syntax and are used in a manner similar to templates. With these new keywords casting becomes easier to understand, find, and maintain.

The basic explicit form of typecasting is the static cast.
 * The basic form of type cast

A static cast looks like this:

The compiler will try its best to interpret the expression as if it were of type type. This type of cast will not produce a warning, even if the type is demoted.

The cast can be used to suppress the warning as shown above. cannot do all conversions; for example, it cannot remove const qualifiers, and it cannot perform "cross-casts" within a class hierarchy. It can be used to perform most numeric conversions, including conversion from a integral value to an enumerated type.

Old C-style casts
Other common type casts exist, they are of the form type(expression) (a functional, or function-style, cast) or (type)expression (often known simply as a C-style cast). The format of (type)expression is more common in C (where it is the only cast notation). It has the basic form:

A C-style cast can, in a single line of source code, make two conversions. For instance remove a variable consteness and alter its type. In C++, the old C-style casts are retained for backwards compatibility.

There are several shortcomings in the old C-style casts:
 * 1) They allows casting practically any type to any other type, leading to lots of unnecessary trouble - even to creating source code that will compile but not to the intended result.
 * 2) The syntax is the same for every casting operation, making it impossible for the compiler and users to tell the intended purpose of the cast.
 * 3) Hard to identify in the source code.

The C++ specific cast keyword are more controlled. Some will make the code safer since they will enable to catch more errors at compile-time, and all are easier to search, identify and maintain in the source code. Performance-wise they are the same with the exception of, for which there is no C equivalent. This makes them generally preferred.