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.