Kevin said:
That's fine, but it's not an argument in favor of malloc-casting, as far
as I can tell. We are talking about the C language, not some theoretical
language similar to C but without implicit conversions from void* to
other pointer types.
There are features of C I do not use because I consider them not useful
or downright ugly. This is one of them; I would be surprised if the same
wouldn't be true for most of us here (trigraphs come to mind).
So for me, at least, this /is/ an argument against implicit void*
conversions, and therefore for explicit malloc casts.
Within the C language as it actually exists, omitting the cast is usually
> (slightly) safer.
This came up in the earlier discussion a few weeks ago. The "missing
#include stdlib.h" argument I think is not very strong, given that any
quality compiler can be made to warn about that nowadays. The argument
that you have to maintain consistency between no less than three type
specifiers when you do:
double *x = (double *)malloc(n * sizeof(double))
....is somewhat stronger, but this is still "taste" territory IMHO. All
in all, I'd have to say that the discussion is not an open-and-shut case
as many here feel it is, since there are also arguments /for/ malloc
casting.
I still see some validity in maintaining C++ compatibility. Essentially,
malloc casts are by far the most important (often only) thing to keep a
valid C program from also being a valid C++ program. Many disagreed,
arguing that I wouldn't try to compile my C program using a Fortran
compiler either. Upon which I responded that actually, I would, if this
could help me to catch errors (which is not the case, as it is with C++).
The second, more philosophical argument, is that I use casts to improve
or correct the compiler's knowledge of the type of an expression. Given
the loose expression malloc(1000 * sizeof(double)), this ought to be of
type double* instead of void*, so I cast. The fact that it is usually
assigned to a variable of type double* immediately after, invoking
implicit conversion, is irrelevant as far as I am concerned; the
expression itself ought to be of type double*, which allows the compiler
to catch errors of the form:
int *x = (double *)malloc(1000 * sizeof(double))
That would go unnoticed on
int *x = malloc(1000 * sizeof(double))
Although many (most here, at least) would prefer
int *x = malloc(1000 * sizeof *x)
Which doesn't suffer from any problem, except that the RHS expression is
of type void*, and needs an implicit conversion due to assignment
(which I don't like).
This basically summarizes the discussion pretty even-handedly, I hope.
The only thing I want to argue is that it's still up for discussion. No
killer arguments are made from both side of the fence I think.
There is no such thing as "implicit casting". A cast is, by definition,
an explicit conversion. An implicit conversion is not a cast.
I'll try to be more careful in the present and future.
As for your warning sign analogy, that's fine. But why would you want to
flag a perfectly safe malloc call with such a warning? Warning signs are
only useful when they are accurate.
Having a block of a thousand doubles floating around on the heap and
pointing to it by a void* to me is a strange situation. I mend it with
the cast. Overriding the type inferred by the compiler is something that
merits a warning for me.
It doesn't "hurt" in the same sense that any unnecessary text (that
neither changes nor clarifies the meaning of the program) doesn't hurt.
You could cast every expression you type, throw in a few dozen
parenthesis for good measure, and have a haiku comment after every line
in your program if you wanted to, and it wouldn't "hurt", at least in
the sense that the program would still behave the same.
My line was a response to the statement that not including the cast
doesn't make a whole lot of difference to the compiler.
Haiku comments and superfluous parentheses, you (and I) don't do that.
However we probably both use indenting and a consisting bracing style.
There's a whole spectrum of things one can do to source code without
altering its meaning, everybody draws a line somewhere.
Of course, this only applies to casts as long as you haven't made a
mistake. Unnecessary casts are harmful (for normal people) mainly
because they can hide mistakes. If you never make a mistake in your
code, then you can certainly cast all you want without any harm.
Incorrect casts are harmful almost by definition. Unnecessary casts, in
my opinion, depends a lot on one's definition of the word "unnecessary".
I have stated my criterion for using casts several times now, which is
overriding the type inferred by the compiler for an expression when I,
the programmer, know better. That's a pretty clear criterion. It's also
a defensible criterion, I think. Followinging this criterion, malloc
casts are no longer unneccesary, but an integral part of my particular
coding style.
What makes you think a pointer cast doesn't generate code?
Experience with modern hardware. Surely the standard allows for
architectures that have type-tagged memory and perhaps there are some
architectures even today that do need to execute code on a pointer type
conversion (either implicit or by cast), but I think it is fair to say
that this is rare. Especially compared to float-to-int conversions, that
must generate code.
If you don't like implicit floating point to integer conversions, you
are free to not use them. Since such a conversion could actually be a
problem (unlike the implicit conversion of malloc's return value), using
a cast as a "warning sign" like you mentioned before may be appropriate.
I think it is, yes.
Best regards,
Sidney