What I meant by my paragraph above is that I force the user to
define the types such that most type conversions / casts are of the
kind described above. Based on the replies here I do plan to rely
more on implicit conversions rather than casting.
I would still like to know more examples of the types of errors
introduced by casting.
Relying on expert opinion is wise, but learning from examples is
more educative.
In most cases where a cast is (mis-)used, assuming the writer got the
type right, the code would mean exactly the same thing without the
cast, because the same conversion will be done explicitly. In such
cases, the cast does nothing but add clutter and introduce a risk of
error that wouldn't be there without the cast. (I suggest, therefore,
that the burden is on the advocate of a cast to demonstrate that it's
useful.)
An example where a cast can introduce an error:
x = (float)y;
Assume y is of some arithmetic type. If x is of type float, this is
ok (but unnecessary). But suppose x is of type double (maybe you
changed the declaration a year after you wrote the original code).
Then the explicit conversion to float will lose precision -- and it
will do so without a peep of complaint from the compiler. If you had
just written:
x = y;
the the implicit conversion would have done the right thing.
A cast tells the compiler, "Shut up, I know what type I want" -- and
sometimes you don't, especially as your code is maintained over time.
C90's "implicit int" rule presents another problem. For example:
some_type *ptr = (some_type*)malloc(sizeof(some_type));
If you forgot the required ``#include <stdlib.h>'', then the compiler
(under C90 rules, changed in C99) *assumes* that malloc is a function
returning int. It actually returns void*. One possibility is that
the call will interpret the void* result as if it were of type int,
and then convert the int value to some_type* (which may or may not
"work" depending on the implementation). Or, if integers and pointers
are returned in different registers, you might get complete garbage.
Most compilers these days will warn about this error if you ask them
nicely, but if you just omit the cast the assignment of an int to
a pointer is illegal.
Of course there are cases where casts are necessary and appropriate.
If you need to convert a pointer to an integer, or vice versa, or
between two different pointer types, you need a cast, since those
conversions aren't done explicitly (other than the special case of a
null pointer constant). Such conversions are implementation-defined,
so you'd better know what you're doing. If you're passing an argument
to a variadic function, the compiler doesn't know the target type,
so you have to specify it yourself:
printf("sizeof(double) = %d\n", (int)sizeof(double));
But in these cases, you *have* to get the target type right; the
compiler won't diagnose an error.
See also the comp.lang.c FAQ, <
http://www.c-faq.com/>.