C++ Typecasting Part 1
Typecasting is the concept of converting the value of one type into another type. For example, you might have a float that you need to use in a function that requires an integer.
Implicit conversion
Almost every compiler makes use of what is called automatic typecasting. It automatically converts one type into another type. If the compiler converts a type it will normally give a warning. For example this warning: conversion from ‘double’ to ‘int’, possible loss of data.
The problem with this is, that you get a warning (normally you want to compile without warnings and errors)
and you are not in control. With control we mean, you did not decide to convert to another type, the compiler did. Also the possible loss of data could be unwanted.
Explicit conversion
The C and C++ languages have ways to give you back control. This can be done with what is called an explicit conversion. Sure you may still lose data, but you decide when to convert to another type and you don’t get any compiler warnings.
Let’s take a look at an example that uses implicit and explicit conversion:
#include <iostream>
using namespace std;
int main()
{
int a;
double b=2.55;
a = b;
cout << a << endl;
a = (int)b;
cout << a << endl;
a = int(b);
cout << a << endl;
}
Note: the output of all cout statements is 2.
The first conversion is an implicit conversion (the compiler decides.) As explained before, the compiler should give a warning.
The second conversion is an explicit typecast, in this case the C style explicit typecast.
The third conversion is also explicit typecast, in this case the C++ style explicit typecast.
Four typecast operators
The C++ language has four typecast operators:
- static_cast
- reinterpret_cast
- const_cast
- dynamic_cast
Static_cast
Automatic conversions are common in every C++ program. You have:
- Standard conversion. For instance: from short to int or from int to float.
- User defined conversions (Class conversions.)
- Conversion from derived class to base class.
(Take a look at the inheritance tutorial)
The static_cast can be used for all these types of conversion. Take a look at an example:
int a = 5;
int b = 2;
double out;
// typecast a to double
out = static_cast<double>(a)/b;
It may take some time to get used to the notation of the typecast statement. (The rumour goes that Bjarne Stroustrup made it difficult on purpose, to discourage the use of typecasting.) Between the angle brackets you place to which type the object should be casted. Between the parentheses you place the object that is casted.
It is not possible to use static_cast on const objects to non-const objects. For this you have to use const_cast. (Further down we take a look at const_cast.)
If an automatic conversion is valid (from enum to int for instance) then you can use static_cast to do the opposite (from int to enum.)
For instance:
enum my_numbers { a=10, c=100, e=1000 };
const my_numbers b = static_cast<my_numbers> (50);
const my_numbers d = static_cast<my_numbers> (500);
Note: We add some new values (b and d). These are type-cast from int to enum.
Reinterpret_cast
The reinterpret_cast is used for casts that are not safe:
- Between integers and pointers
- Between pointers and pointers
- Between function-pointers and function-pointers
For instance the typecast from an integer to a character pointer:
char *ptr_my = reinterpret_cast<char *>(0xb0000);
Note: the example above uses a fixed memory location.
If we use the reinterpret_cast on a null-pointer then we get a null-pointer of the asked type:
char *ptr_my = 0;
int *ptr_my_second = reinterpret_cast<int *>(ptr_my);
The reinterpret_cast is almost as dangerous as an “old fashion” cast. The only guaranty that you get is that if you cast an object back to the original data-type (before the first cast) then the original value is also restored (of course only if the data-type was big enough to hold the value.)
The only difference with an old fashion cast is that const is respected. This means that a reinterpret_cast can not be used to cast a const object to non-const object. For instance:
char *const MY = 0;
// This is not valid because MY is a const!!
int *ptr_my = reinterpret_cast<int *>( MY);
Const_cast
The only way to cast away the const properties of an object is to use const_cast. Take a look at an example:
void a(Person* b);
int main()
{
const Person *ptr_my = new Person("Joe");
a( const_cast<Person *>(ptr_my) );
}
The use of const_cast on an object doesn’t guarantee that the object can be used (after the const is cast away.) Because it is possible that the const-objects are put in read-only memory by the program.
The const_cast can not be used to cast to other data-types, as it is possible with the other cast functions.
Take a look at the next example:
int a;
const char *ptr_my = "Hello";
a = const_cast<int *>(ptr_my);
a = reinterpret_cast<const char*>(ptr_my);
a = reinterpret_cast<int *>(const_cast<char *>(ptr_my) );
Note: casting from const char * to int * isn’t very good (not to say a very dirty trick.) Normally you won’t do this.
The first statement (const_cast) will give an error, because the const_cast can’t convert the type. The second statement (reinterpret_cast) will also give an error, because the reinterpret_cast can’t cast the const away. The third statement will work (mind the note. It is a dirty trick, better not use it.)
That is all for this tutorial. In typecasting part 2 we will look at RTTI, dynamic_cast, typeid and type_info.
Where is link to part-2 ??
@Ashish – I also added a link to typecasting part two in the main text.
nice
It is cool explanation
is it int *a or int a in last example
I have problems:
In the last example:
int a;
a = reinterpret_cast(const char*)(ptr_my);
should be :
int* a;
a = reinterpret_cast(char*)(ptr_my);
If I’m wrong, please correct me.