Type Casting in C
Type casting in C language is a fundamental technique that allows forcing the conversion of a variable from one data type to another. This operation is particularly useful when you want to have precise control over type conversions, avoiding undesired behaviors that might occur with implicit conversions. Explicit casting allows the programmer to clearly indicate to the compiler how to handle the data, improving code readability and maintenance.
In this lesson, we will explore in detail how type casting works in C, when it is useful to use it and what its practical applications are
Explicit Type Conversion: Casting
In the previous lesson we saw how C language handles implicit conversion of arithmetic types. We studied its rules and saw when they apply.
Often, however, we need greater control over type conversion. For these cases, C language provides explicit type conversion which is more commonly called casting.
To perform an explicit cast from one type to another, the following syntax is used:
(type) expression;
Where, type is the data type to which we want to convert the expression and expression is the expression we want to convert.
Let's take an example. Suppose we want to calculate the fractional part of a floating-point number. We can do it very simply by performing an explicit cast:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
We applied the cast at line 10 of the example:
fractional_part = number - (int) number;
In this case, we first converted number to integer through the sub-expression:
(int) number
In this way, we forced the conversion of number to an integer, thus losing the fractional part.
The subsequent operation includes the subtraction between number, which is a float, and (int) number which is an integer. Based on the implicit conversion rules we saw in the previous lesson, before performing the subtraction, the compiler converts the integer (int) number to a float and then executes the subtraction.
For clarity, let's see with a numerical example. Suppose we entered the number 3.14. The variable number will be worth 3.14F. So:
(int) numberwill be worth3. The fractional part is lost in the explicit cast toint;number - (int) numberis a subtraction between afloatand anint. So(int) numberis converted from3to3.0F;- The subtraction
3.14F - 3.0Fis executed and the result is0.14F. This is the value of the fractional part.
Recapping:
Type Casting in C Language
Type Casting, or Explicit Type Conversion, is an operation that allows forcing the conversion of one data type to another.
The syntax to convert one data type to another is the following:
(type) expression;
Where type is the data type to which we want to convert the expression and expression is the expression we want to convert.
Uses of Casting
In C language, casting is essentially used for two purposes:
-
To document a conversion operation that might be performed by the compiler anyway;
For example, if we want to convert a
floatto adouble, we can write:float f; /* ... */ double d = (double) f;Even though the compiler would have performed the implicit conversion, the explicit cast documents the programmer's intention.
In other cases, the compiler avoids showing a warning. For example:
double d; /* ... */ float f = (float) d;In this case the conversion from
doubletofloatmight cause a loss of precision. In the absence of explicit casting, the compiler would have performed the conversion anyway, but would have shown a warning.Through casting, we are essentially telling the compiler that this is an intended behavior and not an oversight.
-
To force a conversion that the compiler would not perform;
Let's take a simple example:
float quotient; int dividend = 15; int divisor = 4; quotient = dividend / divisor;Reading this code, at first glance one might think that the final result, namely the value of the
quotientvariable, is3.75sincequotientis afloat. But this is not the case.In fact, the compiler, first of all, divides
dividendbydivisor. But, since the latter two areint, it performs the division betweenintwhich returns anintand truncates the result to3. Only subsequently, during assignment, the result is converted tofloat. But it will be too late, since the result will already be truncated andquotientwill be worth3.0.In this situation casting comes to our aid. To obtain the correct result,
3.75we must force the compiler to convertdividendordivisortofloatbefore performing the division:quotient = (float) dividend / divisor;Note that we only cast
dividend. This is sufficient since, beingdivisoranint, the compiler will perform the implicit conversion ofdivisortofloatbefore executing the division. -
Avoid cases of overflow.
In some cases, explicit casting is necessary to avoid overflow conditions.
Let's take an example:
long int x; int y = 1000000; x = y * y;At first glance, we might think that the above code is correct. But this is not the case. The result of the multiplication
y * yis1000000000000which can be stored in along intbut not in anint.However, the multiplication between
yand itself is a multiplication betweenintthat returns anint. Only subsequently, during assignment, the result is converted tolong int. But it will be too late, since the result will have already overflowed returning an incorrect result:-727379968.We can avoid this problem by using explicit casting on one of the two operands:
x = ((long) y) * y;In this way, the first operand of the multiplication is converted to
longbefore performing the multiplication. It is not necessary to explicitly convert the second operand since the compiler will perform the implicit conversion tolongbefore executing the multiplication.The result will be correct and
xwill be worth1000000000.
Casting and Precedence Rules
Previously we studied the rules that determine the evaluation precedence of operators in expressions.
In this general scheme, what is the precedence of casting compared to other operators?
C language considers the casting operation, (type), as a unary operator. This means that casting has the same precedence as other unary operators, and therefore has higher precedence than binary operators.
So, returning to the division example we have that the expression:
quotient = (float) dividend / divisor;
is evaluated as:
quotient = ((float) dividend) / divisor;
We could have obtained the same result with the following expression:
quotient = dividend / (float) divisor;
Or, more explicitly:
quotient = (float) dividend / (float) divisor;
In all cases, the result is the same. The casting is performed before the division.
Obviously, in cases where you are not sure about precedence or to make the code more readable, it is always possible to use parentheses to force the evaluation order.
Casting and Precedence Rules
Casting is considered a unary operator and has the same precedence as other unary operators. Therefore, it has higher precedence than binary operators.
To force the evaluation order, it is possible to use parentheses.
In Summary
Type casting is an operation that allows forcing the conversion of one data type to another. This operation is very useful to control type conversion and to avoid undesired behaviors.
We saw in this lesson that:
- Type casting is performed through the syntax
(type) expression;; - Casting is a unary operator and has the same precedence as other unary operators;
- Casting is used to document a conversion operation, to force a conversion that the compiler would not perform and to avoid cases of overflow.