Wondering off topic a bit, why don't [people] think the cast [on
the result of malloc] is wise?
It does nothing in C89 that the language does not already do for
you, and -- in that same standard language -- it hides the frequent
error of failure to #include <stdlib.h>.
C99 requires a diagnostic when calling a function that has not been
declared, so modern C (if one has it available) removes the problem
that omitting the cast solves. (Good C89 compilers may also warn
about calling undeclared functions.) The cast remains useless
adornment, however. Compare with:
int i;
long l;
double d;
... set i to something ...
l = (long)i;
d = (double)i;
Some might argue for just the (double) cast, and some might even
argue for both casts, but I prefer to omit both.
Sloppy type punning is always bad in my opinion.
Casting is not punning -- casting converts values. Punning can be
done via "behind the back" addressing (not always guaranteed to work),
or (works more often but still pretty iffy) unions:
union { unsigned ui; char *cp; } u;
u.cp = "some string";
printf("punned as an int, the string became %x\n", u.ui);
/* WARNING: use of u.ui here is either undefined or, at best,
implementation-defined, although it probably "works" as
long as sizeof(char *) and sizeof(int) are comparable. */
The problem is that a cast is "too strong", overriding
otherwise-required diagnostics for dodgy conversions:
int intfunc();
double *dp;
...
dp = (double *)intfunc(); /* implementation-defined */
This code fragment requires no diagnostics, and usually receives
none.
Also, a C++ compiler will give any error.
A C++ compiler will also do the wrong thing with some C programs.
For instance (note that this program is deliberately constructed,
but similar situations can occur in other, real programs):
#include <stdio.h>
struct A { char c[16]; };
int main(void) {
struct B {
struct A { char c[1024]; } elem;
} localvar;
printf("sizeof(struct A) = %lu\n", sizeof(struct A));
return 0;
}
Predict the output of this program when compiled as C, then again
when compiled as C++. See if your predictions were accurate.
(For these reasons, I recommend using C++ compilers to compile C code
about as often as using Fortran or Ada compilers.
)
You a wrong about minimum sizes returned from malloc. On all systems
that I have worked the minumum size returned is sizeof(double).
I have used systems that round to 2 or 4 bytes, even though
sizeof(double) was 8. These systems used conventional first-fit
or best-fit allocators.
In a system with "bibop" style allocators, in which malloc()s of
different sizes are allocated within different address ranges,
there is of course no requirement that malloc(1) return any more
than a single byte. On the other hand, malloc(9) does appear to
require 8-byte alignment on (e.g.) SPARC systems, where loads or
stores of doubles (whose "sizeof" is 8) must occur on 8-byte
boundaries. (I am not 100% sure of this; these kind of picky
details tend to require careful study of the standards.)