The malloc
function reserves a block of memory in the heap (the dynamic memory pool), and returns a pointer to the first element of that block of memory. That memory is reserved until you call free
, or the program exits.
In the call
pi = (int *) malloc(sizeof(int));
malloc
reserves a block of memory large enough to store a single int
value, and the pointer to that memory block is assigned to pi
. You do not need to cast the result of malloc
1, and it's actually considered bad practice2. A better way to write that would be
pi = malloc( sizeof *pi );
The expression *pi
has type int
, so sizeof *pi
is equivalent to sizeof (int)
3. The advantage of using sizeof *pi
over sizeof (int)
(as well as dropping the cast) is that if you ever change the type of pi
(from int *
to long *
, for example), you won't have to change anything in the malloc
call; it will always allocate the right amount of memory regardless of the type of pi
. It's one less maintenance headache to worry about.
Similarly, the call
pcl = (char *) malloc(strlen("Dynamic String") + 1);
reserves enough memory to hold the contents of "Dynamic String"
(the +1 is necessary for the string terminator) and assigns the pointer to that memory to pcl
. Again, this would be better written as
pcl = malloc( strlen("Dynamic String") + 1 ); // no cast
sizeof (char)
is 1 by definition, so you don't need an explicit sizeof *pcl
in the call above; however, if you ever decide to change the type of pcl
from char *
to wchar_t *
, it would be good to have it in place, although you'd still have to change the string literal and change how you compute the length, so it's not maintenance-free.
The general form a malloc
call is
T *p = malloc( num_elements * sizeof *p ); // where num_elements > 1
or
T *p;
...
p = malloc( num_elements * sizeof *p );
There is a similar function named calloc
that will zero out the allocated memory block:
T *p = calloc( num_elements, sizeof *p );
or
T *p;
...
p = calloc( num_elements, sizeof *p );
1. In C, anyway; C++ does require the cast, since C++ does not allow implicit conversions between void *
and other pointer types. But you shouldn't be using malloc
in C++ code, anyway.
So why do people still cast the result of malloc
in C? It's largely a holdover from pre-ANSI days (more than a quarter of a century ago), when malloc
returned char *
, which cannot be assigned to a different pointer type without a cast. The 1989 standard introduced the void *
type, which is essentially a "generic" pointer that can be assigned to other pointer types without an explicit cast.
2. Under the C89 standard, if the compiler sees a function call without having seen a declaration for that function, it will assume that the function returns int
. Thus, if you forget to include stdlib.h
or otherwise don't have a declaration for malloc
in scope, the compiler will assume it returns an int
value and generate the machine code for the call accordingly. However, int
and pointer types aren't compatible, and normally the compiler will issue diagnostic if you try to assign one to the other. By using the cast, however, you supress that diagnostic, and you may run into runtime problems later on.
The 1999 standard did away with implicit int
typing for functions, so that's not really a problem anymore, but the cast is still unnecessary and leads to maintenance problems.
3. sizeof
is an operator, not a function; parentheses are only required if the operand is a type name like int
or double
or struct blah
.