18.2.2: Cast Operators

[This section corresponds to the second half of K&R Sec. 2.7]

Most of the time, C performs conversions between related types automatically. (See section 18.2.3 for the complete story.) When you assign an int value to a float variable or vice versa, or perform calculations involving mixtures of arithmetic types, the types are converted automatically, as necessary. C even performs some pointer conversions automatically: malloc returns type void * (pointer-to-void), but a void * is automatically converted to whatever pointer type you assign (say) malloc's return value to.

Occasionally, you need to request a type conversion explicitly. Consider the code

	int i = 1, j = 2;
	float f;
	f = i / j;
Recall that the division operator / results in an integer division, discarding the remainder, when both operands are integral. It performs a floating-point division, yielding a possibly fractional result, when one or both operands have floating-point types. What happens here? Both operands are int, but the result of the division is assigned to a float, which would be able to hold a fractional result. Is the compiler smart enough to notice, and perform a floating-point division? No, it is not. The rule is, ``if both operands are integral, division is integer division and discards any remainder'', and this is the rule the compiler follows. In this case, then, we must manually and explicitly force one of the operands to be of floating-point type.

Explicit type conversions are requested in C using a cast operator. (The name of the operator comes from the term typecast; ``typecasting'' is another term for explicit type conversion, and some languages have ``typecast operators.'' Yet another term for type conversion is coercion.) A cast operator consists of a type name, in parentheses. One way to fix the example above would be to rewrite it as

	f = (float)i / j;
The construction (float)i involves a cast; it says, ``take i's value, and convert it to a float.'' (The only thing being converted is the value fetched from i; we're not changing i's type or anything.) Now, one operand of the / operator is floating-point, so we perform a floating-point division, and f receives the value 0.5.

Equivalently, we could write

	f = i / (float)j;
or
	f = (float)i / (float)j;
It's sufficient to use a cast on one of the operands, but it certainly doesn't hurt to cast both.

A similar situation is

	int i = 32000, j = 32000;
	long int li;
	li = i + j;
An int is only guaranteed to hold values up to 32,767. Here, the result i + j is 64,000, which is not guaranteed to fit into an int. Even though the eventual destination is a long int, the compiler does not look ahead to see this. The addition is performed using int arithmetic, and it may overflow. Again, the solution is to use a cast to explicitly convert one of the operands to a long int:
	li = (long int)i + j;
Now, since one of the operands is a long int, the addition is performed using long int arithmetic, and does not overflow.

Cast operators do not have to involve simple types; they can also involve pointer or structure or more complicated types. Once upon a time, before the void * type had been invented, malloc returned a char *, which had to be converted to the type you were using. For example, one used to write things like

	int *iarray = (int *)malloc(100 * sizeof(int));
and
	struct list *lp = (struct list *)malloc(sizeof(struct list));
These casts are not necessary under an ANSI C compiler (because malloc returns void * which the compiler converts automatically), but you may still see them in older code.


Read sequentially: prev next up top

This page by Steve Summit // Copyright 1996-1999 // mail feedback