[comp.lang.c] Casting malloc

Kevin_P_McCarty@cup.portal.com (12/13/89)

This is a question on recommended style.

In ANSI C, assigning a void pointer to any pointer variable is
legal, so casting the value returned by malloc() to the
appropriate pointer type is no longer necessary.  As a matter of
recommended style, should the redundant cast be retained?

Casting malloc() is de rigueur in pre-ANSI environments.  Lint
complains about suspicious pointer conversions when casts are not
used.  This made a virtue of necessity by training the programmer
to rely less on automatic conversions (which is a minefield for
the beginner), and to document "possibly doubtful" constructions.

Variants:

        p = (type *) malloc(sizeof(type));
        p = (type *) malloc(sizeof(*p));    /* except with void *p */
        p = malloc(sizeof(type));
        p = malloc(sizeof(*p))              /* except with void *p */

With an ANSI compliant compiler, the cast is unnecessary.  There
are arguments pro and con for continuing the casting style.

Arguments against casting:

- When the appropriate header is included, casting the result
of malloc is unnecessary.  A cast is just redundant clutter;
mention of the type of variable being malloc'ed occurs with
sizeof.

- When the appropriate header is ommitted, a cast will suppress a
helpful diagnostic, and at worst can result in the return value
from malloc() being silently munged beyond use.

Arguments for:

- Forgetting to include header files now seems to me to be the
kind of sloppy lapse of discipline that "forgetting" to declare
variables is.  ("What?  You didn't include header files?  Take
your code back and clean it up, and come back when you have a
*real* problem!"  :-)).  A more common kind of error (for me at
least) is

        p = (type_A *) malloc(n * sizeof(type_A));

but p was declared as (type_B *).  Omitting the cast will hide
this error.  This argument hinges on what is the most likely
or serious kind of error we can expect programmers to make.

- Some ANSI-aware compilers will complain upon encountering a
function call for which no prototype has been seen.  This is a
Good Thing, to be encouraged, but is a quality of implementation
issue and can't be relied on.

- A practical consideration is the likelihood of needing to
port to pre-ANSI environments which will want casting anyway.
This alone will probably cause me to use casts with malloc()
until ANSI compilers become widespread.

- The habit of casting malloc is apparently so strong that it
survived into the 2nd edition of K&R (pp. 142-143), which says
that "the proper method is to declare that malloc returns a
pointer to void, then explicitly coerce the pointer into the
desired type with a cast."  If you indulge this habit, you are at
least in prestigious company.

(I suppose some might think this settles the question, but
appealing to the authority of the Wise Ones doesn't make the
counterarguments any less cogent.)

bright@Data-IO.COM (Walter Bright) (12/14/89)

In article <24969@cup.portal.com> Kevin_P_McCarty@cup.portal.com writes:
<In ANSI C, assigning a void pointer to any pointer variable is
<legal, so casting the value returned by malloc() to the
<appropriate pointer type is no longer necessary.  As a matter of
<recommended style, should the redundant cast be retained?

Yes. In C++, implicit casts of (void *) to (any *) is not allowed.
The 'redundant' cast is required in C++ code. Since C++ is the way
C is moving, leave the cast in.

<- When the appropriate header is ommitted, a cast will suppress a
<helpful diagnostic, and at worst can result in the return value
<from malloc() being silently munged beyond use.

C++ solves this problem by *requiring* functions to be prototyped before
use. This eliminates the nasty problems caused by forgetting to declare
malloc.

<- Some ANSI-aware compilers will complain upon encountering a
<function call for which no prototype has been seen.  This is a
<Good Thing, to be encouraged, but is a quality of implementation
<issue and can't be relied on.

It's required in C++, and can be relied on.

msb@sq.sq.com (Mark Brader) (12/19/89)

An article which, curiously, was posted to the USA only, asks:

> In ANSI C, assigning a void pointer to any pointer variable is
> legal, so casting the value returned by malloc() to the
> appropriate pointer type is no longer necessary.  As a matter of
> recommended style, should the redundant cast be retained?

I would advise retaining the cast for a few years until (a) there *is*
such a thing as ANSI C, and (b) its use is widespread.  Before that time
there is too much probability of wanting to port back to older compilers.

Once such porting really is not a problem, then I would strongly recommend
removal of the cast.  The statements

	foop = malloc (sizeof *foop);
	foolistp = malloc (n * sizeof *foolistp);

contain NO MENTION of the type of *foop or *foolistp, which makes it
impossible to get it wrong.

Those who say "implicit type conversion is a bug, not a feature" will
disagree.  My opinion is that it is a feature.

A followup suggested that the cast is required in C++ and should there-
fore be used in C.  My opinion is that C++ should "therefore" be fixed.

-- 
Mark Brader		    "'A matter of opinion'[?]  I have to say you are
SoftQuad Inc., Toronto	      right.  There['s] your opinion, which is wrong,
utzoo!sq!msb, msb@sq.com      and mine, which is right."  -- Gene Ward Smith

This article is in the public domain.

markh@csd4.csd.uwm.edu (Mark William Hopkins) (12/27/89)

In article <24969@cup.portal.com> Kevin_P_McCarty@cup.portal.com writes:
>This is a question on recommended style.
>
>In ANSI C, assigning a void pointer to any pointer variable is
>legal, so casting the value returned by malloc() to the
>appropriate pointer type is no longer necessary.  As a matter of
>recommended style, should the redundant cast be retained?

One way around the issue is to define the macro:

#define make(Type) (Type *)malloc(sizeof(Type))

or, perhaps:

#define make(Type, N) (Type *)malloc((N)*sizeof(Type))

and use it to replace malloc as much as possible.

If you're going to use information about the Type anyway (in sizeof()), you
might as well cast malloc and then hide everything.

So you can have it both ways: extra (potentially useful) information,
without the clutter, and not only that, but with LESS clutter than if you
had just decided to eliminate the type casting out of a concern for making
the code less cluttered.

And if that isn't enough, you can modify it easily without ever even touching
on the issue of whether malloc should be casted or not:

#ifdef ANSI
#define make(Type) malloc(sizeof(Type))
#else
#define make(Type) (Type *)malloc(sizeof(Type))
#endif

... presumably this would be in a header file, all invisible to the normal
programmer.