It is not recommended to do the cast to the outcome of malloc()
for the compiler to indicate the missing error of the #include <stdlib.h>
.
As the compiler has no information about the type of result of malloc()
it assumes that this function returns a value of type int
. Afterward
v = (int *) malloc(sizeof(int));
the explicit conversation converts this int
(at this point you have already invoked UB, as you treat the returned value as if it were a different type that it actually is) in a int *
. Note that this conversation is not valid, but as it was an explicit request of the programmer the compiler does not complain. Finally the new (invalid) type value int *
is assigned to variable.
Without the explicit conversation, the compiler would complain about the automatic conversation between int
(the type of value it assumes to function malloc()
returns) and int *
--- which would lead the (experienced) programmer to add the header correct.
More notes
Without #include <stdlib.h>
int *v, *x, *z;
v = (int *)malloc(sizeof (int)); /* 1a */
z = (int)malloc(sizeof (int)); /* 2a */
x = malloc(sizeof (int)); /* 3a */
With #include <stdlib.h>
#include <stdlib.h>
/* ... */
int *v, *x, *z;
v = (int *)malloc(sizeof (int)); /* 1b */
z = (int)malloc(sizeof (int)); /* 2b */
x = malloc(sizeof (int)); /* 3b */
1st -- ERROR
The malloc()
returns a type value int *
which is assumed to be int
due to the absence of the correct prototype. In addition, the explicit conversion of this int
for int *
is not valid, but as it was an explicit request of the programmer, the compiler does not complain.
1b -- Redundancy
Like the malloc()
returns a type value void *
, this value would be automatically converted to int *
during the allocation to v
(pointers to void
are compatible with pointers for any type). Redundancy is not an error, but is unnecessary. No one writes return ((((42)))); /* parenteses redundantes */
2a -- Error and redundancy
In the first case we have a type value void*
returned by malloc()
interpreted as int
because of the absence of header correct. After that we have the redundancy of asking for the conversation of int
in int
. Next, the assignment of a type value int
the type variable int *
is wrong, but the compiler has to complain. Note that in this case the error has nothing to do with the use made of malloc()
or the conversation of the result. The assignment of a int
to a int *
this wrong.
2b -- ERROR
As in 2a, the error has nothing to do with the use of malloc()
or the value returned.
3a -- Error that the compiler complains and easily corrects
When the compiler complains about assigning a type value int
to a type variable int *
(the gcc has an error-inducing text for this spike error), the programmer notices that it lacked header include <stdlib.h>
.
3b -- OK
Correct way to use malloc()
.
One more tip (to avoid future problems if the type of variable changes, for example int capacidade
for double capacidade
)
int *capacidade;
/* ... */
capacidade = malloc(200 * sizeof (int));
/* ... */
free(capacidade);
At a certain point someone remembers that it will be necessary to have, for example, 3.14159 capacity and decide to change the type to double
. In these conditions it will be necessary to change the code in 2 locations: in the definition and in the allocation.
Using the object itself in the allocation, only changes in the definition
double *capacidade;
/* ... */
capacidade = malloc(200 * sizeof *capacidade); // usa o tipo do objecto
/* ... */
free(capacidade);