1) One should aviod using casts while writing a program that is
supposed to be portable. casts are sign of bad design.
Let's be a bit more pedantic and restrict that to pointer casts.
Casting "normal" values is quite common, you may often see in C89
programs e.g.
char hw[ ] = "Hello world!";
printf( "%lu\n", ( unsigned long ) strlen( hw );
to convert the size_t type return value of strlen() to something you
can print with one of the available format specifier (in C99 you bet-
ter would drop the cast and use "%zu" in the format string instead) or
double d = 42.1234;
int i = ( int ) d;
to assign the integer part of 'd' to 'i', snipping off the fractional
part.
And while casting pointers is often a sign of some trouble in a program,
there exist a few cases where they it's actually required, mostly in
conjunction with arguments of variadic functions.
[...]
Most casts are unnecessary because, in most contexts, the value will
be implicitly converted to the required type.
Variadic functions are probably the major exception to this rule. For
example, printf with a "%p" specifier expects a void*; if you want to
pass it an int*, you have to explicitly convert it. (A non-variadic
equivalent would convert from int* to void* implicitly.) printf with
a "%lu" expects an unsigned long; if you want to pass it a foo_t, you
have to convert it. (For size_t, C99 provides "%zu", but it can't
cover everything.)
If you see a cast in a context other than a call to a variadic
function, it's likely to be either unnecessary (specifying a
conversion that would have been done implicitly without the cast), or
potentially dangerous (performing a non-trivial conversion when it
very likely would have been better to use the correct type in the
first place).
In your example:
double d = 42.1234;
int i = ( int ) d;
the cast is actually unnecessary; it could have been written as
double d = 42.1234;
int i = d;
It's tempting to use the cast anyway, since it makes the conversion
expicit and numeric conversions aren't as dangerous as pointer
conversions. On the other hand, if during maintenance the type of
i is changed from int to long, but you forget to change the cast:
double d = 42.1234;
long i = ( int ) d;
you could be introducing a subtle bug that may be very difficult to
track down. (It's obvious in this example, but would be less so if
the assignments are far from the declarations.) That's another
drawback of the cast operator: the syntax requires you to specify the
target type by name, but sometimes what you really want is the type of
the target, whatever that happens to be. (A typeof operator might be
useful here -- not that I'm suggesting adding it to the language.)
One case where a numeric cast is necessary is when you want to control
when the conversion takes place. For example:
int x = 1;
int y = 3;
double z = (double)x/y;
Without the cast, z would be assigned the value 0.0.
By using a cast, you're promising the compiler that you know what
you're doing. You'd better be right.