In the previous lesson 6.14 -- Implicit type conversion (coercion), we discussed that the compiler can implicitly convert a value from one data type to another through a system called implicit type conversion
. When you want to promote a value from one data type to a larger similar data type, using implicit type conversion
is fine.
However, many new programmers try something like this: float f = 10 / 4;
. However, because 10
and 4
are both integers, no promotion takes place. Integer division is performed on 10 / 4
, resulting in the value of 2
, which is then implicitly converted to 2.0
and assigned to variable f
!
In the case where you are using literal values (such as 10
, or 4
), replacing one or both of the integer literal value with a floating point literal value (10.0
or 4.0
) will cause both operands to be converted to floating point values, and the division will be done using floating point math (and thus retain the fractional component).
But what if you are using variables? Consider this case:
1 2 3 |
int i1 { 10 }; int i2 { 4 }; float f { i1 / i2 }; |
Variable f
will end up with the value of 2
. How do we tell the compiler that we want to use floating point division instead of integer division? The answer is by using a type casting operator
(more commonly called a cast
) to tell the compiler to do explicit type conversion. A cast represents an request by the programmer to do an explicit type conversion
.
Type casting
In C++, there are 5 different types of casts: C-style casts
, static casts
, const casts
, dynamic casts
, and reinterpret casts
. The latter four are sometimes referred to as named casts.
We’ll cover C-style casts
and static casts
in this lesson. Dynamic casts
we’ll save until after we cover pointers
and inheritance
in future lessons.
Const casts
and reinterpret casts
should generally be avoided because they are only useful in rare cases and can be harmful if used incorrectly.
Warning
Avoid const casts and reinterpret casts unless you have a very good reason to use them.
C-style casts
In standard C programming, casts are done via the () operator, with the name of the type to convert the value to placed inside the parenthesis. For example:
1 2 3 |
int i1 { 10 }; int i2 { 4 }; float f { (float)i1 / i2 }; |
In the above program, we use a float C-style cast to tell the compiler to convert i1
to a floating point value. Because the left operand of operator/ now evaluates to a floating point value, the right operator will be converted to a floating point value as well, and the division will be done using floating point division instead of integer division!
C++ will also let you use a C-style cast
with a more function-call like syntax:
1 2 3 |
int i1 { 10 }; int i2 { 4 }; float f { float(i1) / i2 }; |
This performs identically to the prior example.
Although a C-style cast
appears to be a single cast, it can actually perform a variety of different conversions depending on context. This can include a static cast
, a const cast
or a reinterpret cast
(the latter two of which we mentioned above you should avoid). As a result, C-style casts
are at risk for being inadvertently misused, and not producing the expected behavior, something which is easily avoidable by using the C++ casts instead.
As an aside...
If you’re curious, this article has more information on how C-style casts actually work.
Warning
Avoid using C-style casts.
static_cast
C++ introduces a casting operator called static_cast, which can be used to convert a value of one type to a value of another type.
You’ve previously seen static_cast
used to convert a char
into an int
so that std::cout prints it as an integer instead of a char
:
1 2 |
char c { 'a' }; std::cout << c << ' ' << static_cast<int>(c) << '\n'; // prints a 97 |
The static_cast
operator takes a single value as input, and outputs the same value converted to the type specified inside the angled brackets. Static_cast
is best used to convert one fundamental type into another.
1 2 3 4 5 |
int i1 { 10 }; int i2 { 4 }; // convert an int to a float so we get floating point division rather than integer division float f { static_cast<float>(i1) / i2 }; |
The main advantage of static_cast
is that it provides compile-time type checking, making it harder to make an inadvertent error. Static_cast
is also (intentionally) less powerful than C-style casts
, so you can’t inadvertently remove const or do other things you may not have intended to do.
Best practice
Favor static_cast when you need to convert a value from one type to another type
Using casts to make implicit type conversions clear
Compilers will often complain when an unsafe implicit type conversion is performed. For example, consider the following program:
1 2 |
int i { 48 }; char ch = i; // implicit conversion |
Casting an int (4 bytes) to a char (1 byte) is potentially unsafe (as the compiler can’t tell whether the integer will overflow the range of the char or not), and so the compiler will typically complain.
To get around this, we can use a static cast to explicitly convert our integer to a char:
1 2 3 4 |
int i { 48 }; // explicit conversion from int to char, so that a char is assigned to variable ch char ch = static_cast<char>(i); |
When we do this, we’re explicitly telling the compiler that this conversion is intended, and we accept responsibility for the consequences (e.g. overflowing the range of a char
if that happens). Since the output of this static_cast
is of type char
, the assignment to variable ch
doesn’t generate any type mismatches, and hence no warnings.
In the following program, the compiler will typically complain that converting a double
to an int
may result in loss of data:
1 2 |
int i { 100 }; i = i / 2.5; |
To tell the compiler that we explicitly mean to do this:
1 2 |
int i { 100 }; i = static_cast<int>(i / 2.5); |
Quiz time
![]() |
![]() |
![]() |
Leave a Reply