What exactly is a type cast in C/C++?
A type cast is basically a conversion from one type to another. It can be implicit (i.e., done automatically by the compiler, perhaps losing info in the process) or explicit (i.e., specified by the developer in the code). The space occupied by the types is of secondary importance. More important is the applicability (and sometimes convenice) of conversion.
It is possible for implicit conversions to lose information, signs can be lost / gained, and overflow / underflow can occur. The compiler will not protect you from these events, except maybe through a warning that is generated at compile time. Slicing can also occur when a derived type is implicitly converted to a base type (by value).
For conversions that can be downright dangerous (e.g., from a base to a derived type), the C++ standard requires an explicit cast. Not only that, but it offers more restrictive explicit casts, such as static_cast
, dynamic_cast
, reinterpret_cast
, and const_cast
, each of which further restricts the explicit cast to only a subset of possible conversions, reducing the potential for casting errors.
Valid conversions, both implicit and explict are ultimately defined by the C/C++ standards, although in C++, the developer has the ability to extend conversions for user defined types, both implicit and explicit, via the use of constructors and overloaded (cast) operators.
The complete rules for which casts are allowed by the standards and which are not can get quite intricate. I have tried to faithfully present a somewhat concise summary of some of those rules in this answer. If you are truly interested in what is and is not allowed, I strongly urge you to visit the standards and read the respective sections on type conversion.
Just want to mention something frequently overlooked:
- A cast always creates a temporary of the target type (although if the target type is a reference, you won't notice).
This can be important. For example:
#include <iostream>
void change_one_print_other( int& a, const int& b )
{
a = 0;
std::cout << b << "\n";
}
int main(void)
{
int x = 5, y = 5;
change_one_print_other(x, x);
change_one_print_other(y, static_cast<int>(y));
}
That cast LOOKS useless. But looks can be deceiving.
There are certain type casts that the compiler knows how to do implicitly - double to int is one of them. It simply drops the decimal part. The internal representation is converted as part of the process so the assignment works correctly.
Note that there are values too large to be converted properly. I don't remember what the rules are for that case; it may be left at the discretion of the compiler.