Malcolm said:
[...]
With the exception of casts from floating point types to integers, C casts
are simple reinterpretations of bits. If the bit pattern doesn't make sense
for the type you are casting to, you will get garbage results and the
compiler won't warn about them.
Nonsense. Here are a few examples of casts that are
*not* mere "reinterpretations of bits" on most implementations:
(long)0
`0' has type `int', which might have as few as sixteen
bits. `(long)0' has type `long', which has at least
thirty-two. What sort of "reinterpretation" created
the additional bits?
(double)1u
`1u' has type `unsigned int', and exactly one of its
bits is non-zero. `(double)1u' has type `double', and
the number of non-zero bits is unspecified. How did
"reinterpretation" arrive at different values for
corresponding bit positions?
(float)1.0
`1.0' has type `double', usually represented as a 64-
bit value. `(float)1.0' has type `float', usually
represented in 32 bits. How did "reinterpretation"
destroy 32 bits?
(double*)NULL
This one's trickier, since the Standard doesn't specify
the type of the expression `NULL'. However, one of the
allowed types for `NULL' is `void*', and on a platform
where this is so it may also be the case that a `void*'
value has more bits than a `double*'. On a platform
where `NULL' has type `int', it is not necessarily the
case that a `double*' has the same number of bits as
an `int', nor that all the bits of `(double*)NULL' are
zeros. See Question 5.17 in the comp.lang.c FAQ --
in fact, read all of Section 5; it will do you good.
A cast is an operator, just like `+' or `%'. Almost all[*]
C operators work with the values of their operand or operands,
and none[**] works with the representations.
[*] The only operators I can think of that do not use their
operands' values are `sizeof' and unary `&', but perhaps
I've overlooked something.
[**] Perhaps it's debatable, but I consider this true even of
the bitwise operators: binary `&', `|', and `^'. They
are described as operating on the binary digits of their
operand values, but that's a convenience, an aid to
clarity of exposition. In particular, note that they are
not defined to operate on any "padding bits," which are
part of the representation (if present), but not part of
the value.
C programmers are often tempted to think about the representations
of the values their programs manipulate. IMHO this is a temptation
worth resisting: if you concentrate on the values themselves and
let the implementation figure out how to represent them, you will
be a happier programmer in the long run.