Functionally, all three are equivalent.
Stylistically, 1 is the preferred option (at least by me and a number of other C programmers). Note that sizeof
is an operator, not a function, and parentheses are only required when the operand is a type name. So you could write sizeof *item
as opposed to sizeof (*item)
- the parens don't hurt anything except readability. Also note that sizeof
does not attempt to evaluate its argument (it won't try to dereference item
); all it does is compute the number of bytes required by the resulting type, and it does that at compile time, not run time.
As far as C is concerned, you should not cast the result of malloc
. As of the 1989 standard it's no longer necessary; malloc
returns a void *
, which can be assigned to any other pointer type without needing an explicit cast1.
Under the C89 standard, casting the result of malloc
could suppress a useful diagnostic if you forgot to include stdlib.h
or otherwise didn't have a declaration for malloc
in scope. C89 still allowed implicit int
declarations; if the compiler saw a function call in the code without a declaration, it assumed the function returned an int
value. If you left off the cast, the compiler would complain that you were trying to assign an integer value to a pointer object. With the cast, the compiler would compile the code without a diagnostic, but you'd be converting a pointer value to an int
and back to a pointer again, which may or may not work.
The C99 standard got rid of implicit int
declarations, so that isn't a problem anymore; cast or not, you'll get a diagnostic if you forget to include stdlib.h
. You should still leave the cast off for readability and maintainability reasons; all it does is add useless visual clutter. If you change the declaration of the target (from struct foo *
to struct bar *
), then you'd have to update the cast as well, which is just extra work, and if you forget to do it then it's a bug. item = malloc( sizeof *item )
will always do the right thing without any further maintenance, no matter what changes you make to the type of item
.
C++, being a different language from C with different rules, does not allow you to assign a void *
to another pointer type without an explicit cast, so you would have to cast the result of malloc
in that case. This is an issue if you're migrating from C to C++ and haven't redone all your dynamic memory management code (which is the only excuse for using malloc
in C++ code). As a matter of course, you should not use malloc
/calloc
/realloc
in C++; either use one of the standard containers, or use the new
operator.
1 - Prior to the C89 standard, malloc
, calloc
, and realloc
all returned char *
, so a cast was required if the target was a different pointer type. Unfortunately, the habit persisted even though it was no longer necessary