Introduction
Casting is the action of temporarily converting one type to another. A
common use is in arithmetic expressions. If you have two counts recorded as
integers but you want to calculate the ratio of the two counts;
int one,two;
the expression one/two will be truncated as an integer, losing the decimal
part of the answer. To handle this, you can cast the two integers into
floats.
float three;
three= (float) one / float(two);
or
three= (float)(one/two);
Casting tricks the type system of the compiler.
It is best to use it sparingly.
It is also a little hard to find the places in your code where
you use it.
The C compiler does some implicit casting.
For example, from int to char and back.
Another common use of casting is in pointer handling.
When arithmetic is
done on pointers, for example in the expression ptr++, there is an implicit
cast from the pointer type to integer to allow addition.
In addition, the
compiler knows how much to add to the pointer address to get the next
object.
If you have an array of integers like this:
int arr[10];
int * iptr;
iptr=arr;
Iptr now contains the address of the first element of the array arr.
The expression iptr++ increases the value in iptr by the size of an integer so
the iptr now contains the address of the second element in the array.
Since a char is one byte (ignoring UNICODE) a character pointer is the lowest
common denominator of pointers.
So the malloc() function returns a
character pointer to the allocated space.
The user than casts the returned
character pointer into the pointer type needed.
C++ provides some more explicit forms of casting.
There are 4 types of cast operators in C++:
dynamic_cast
The dynamic_cast is used to downcast or convert from a a base type to a
derived type. If you have
class one {};
class two : public one {};
You can always cast a b to an a (upcast) as an object of class a is larger
or equal in size to an object of class b.
However, the other direction only makes sense if the object of type a is
actually a type b object. The dynamic_cast operator returns the address of
the the cast object or null if the source object isn't the child type.
so if
one foo;
if dynamic_cast<two *> (&foo) returns null than foo isn't actually a two type
object.
static_cast
This is most like the traditional cast. It is used for casts that are
typically left implicit, like float to int or int to long. Also casts
larger types into smaller. This includes float to int or long to int.
Casting a larger type like long to a smaller type like int may result in
lost digits.
Some examples:
int i; long l; float f;
i=f;
i=l;
i=static_cast<int>l);
i=static_cast<int>f);
It is also used to convert pointers from void,
float *fp;
void * vp;
fp= static_cast<float *>vp;
const_cast
This is a strange addition to the language. It allows you to convert a
const to a non-const or a volatile to non volatile. For example:
const in i = 0;
To get a pointer to this variable. Normally this isn't allowed as you can't
get a pointer to a const object that isn't stored in a const pointer
variable.
int * j = const_cast<int *>i);
reinterpret_cast
This is the most dangerous cast. It pretends that the one object is just a
bunch of bits and the cast changes it to another bunch of bits. If the two
types are different, chaos can result. This is rarely if ever needed.