Typecast of malloc is recommended?

6

I have already read that it is not recommended to do typecast of malloc when allocating memory for a new pointer variable, and a lot of sites and books teach this practice in memory allocation, left with some doubts.

  • Why is it not recommended to do typecast of malloc ?
  • What kind of complications this practice can bring to my program?

A example with and without typecast of malloc to illustrate the situation:

#include <stdio.h>

int main(void)
{
    int * v, * x, * z;
    v = (int *) malloc(sizeof(int));
    z = (int) malloc(sizeof(int));
    x = malloc(sizeof(int));

    *v = 10;
    *x = 5;
    *z = 50;

    printf("v=%i\nx=%i\nz=%i", *v, *x, *z);

    return 0;
}
    
asked by anonymous 13.04.2016 / 20:43

3 answers

5

Like many authors and as written in the article C-faq Malloc Cast , all say that typecast in C , is not necessary, and due to auto-handling of void * types for other types, then they suggest not to make use of it, but there are cases where typecast will still be needed.

  

What is the purpose of typecast ?

typecast serves only to make a pseudo-conversion. This means that the value of the variable is not converted, but masked. Ex:

char c[] = {244,1,0,0}; // vetor de char com 4 posições
int *n; // ponteiro de inteiro
n = c;

printf("%d\n", *n);
  

c saves the values [244] [1] [0] [0] .

     

c is a vector of 4 bytes.

     

n has the size of 4 bytes as well as c

When you assign c to n , it will not give error, because the content to store values of both is the same. What happens is that char * is different from int * , and this generates an alert indicating that.

Some languages like Java and C ++ would not allow this assignment because they are different types. And that's where the typecast

n = (int *) c;

This prevents the compiler from sending an alert for different types of variables. And that's exactly what happens when using malloc . Return void * is only being treated as int * , char * , or which you are using.

Conclusion:

It is not as if typecast is not recommended or feasible, it is not necessary (on occasion). Using typecast to pass values from float to int , and unsigned to signed is used and does not use it, can end up causing problems for your code, but can also mask some errors like size difference of structures and things like, but are some problems caused by carelessness of the programmer himself.

References:

c-fac

Typecast in C OS

Typecast is necessery

Pontov

TIExpert

    
14.04.2016 / 01:47
3

It is not really recommended to perform typecast, at least in C. The return of malloc is essentially a pointer to void (void *), and is then implicitly converted to another type of pointer.

As complications, I say from experience, the use of typecasts in C may come to mask problems that the compiler would ideally identify.

More information in the C-FAQ link

    
14.04.2016 / 00:07
3

It is not recommended to cast to the result of malloc() for the compiler to indicate the failure of #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 . Then

v = (int *) malloc(sizeof(int));

Explicit conversion converts this int (at this point you invoked UB, because you treat the returned value as if it were a different type than it actually is) in int * . Note that this conversion is not valid, but as it was an explicit request from the programmer the compiler does not complain. Finally the new value (invalid) of type int * is assigned to variable.

Without the explicit conversion, the compiler would complain about the automatic conversion between int (the type of value it assumes that the function malloc() returns) and int * --- which would take the programmer (experienced) to add the correct header .

More notes

No #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 */

1a - ERROR

The malloc() returns a value of type int * which is assumed to be int due to the absence of the correct prototype. Also, the explicit conversion of this int to int * is not valid, but since it was an explicit request from the programmer, the compiler does not complain.

1b - Redundancy

As malloc() returns a value of type void * , this value would be automatically converted to int * during the assignment to v (pointers to void are compatible with pointers to any type). Redundancy is not an error, but it is unnecessary. No one writes return ((((42)))); /* parenteses redundantes */

2a - Error and redundancy

In the first case we have a value of type void* returned by malloc() interpreted as int because of the absence of the correct header . After that we have the redundancy to request the conversion of int to int . Next, assigning a value of type int to% variable of type int * is wrong, but the compiler has to complain. Note that in this case the error has nothing to do with the use of malloc() or conversion of the result. The assignment of int to int * is wrong.

2b - ERROR

As in 2a, the error is not about the use of malloc() or the conversion of the returned value.

3a - Error that the compiler complains and easily corrects

When the compiler complains about assigning a value of type int to a variable of type int * (gcc has text that misleads this specific error), the programmer Note that you did not include the header <stdlib.h> .

3b - OK

Correct way to use malloc() .

More a tip (to avoid future problems if the variable type changes, for example, from int capacidade to double capacidade )

    int *capacidade;
    /* ... */
    capacidade = malloc(200 * sizeof (int));
    /* ... */
    free(capacidade);

At some point in time someone remembers that it will be necessary to have, for example, 3.14159 capacity and it is decided to change the type to double . In these conditions it will be necessary to change the code in 2 places: in the definition and in the allocation. Using the object itself in the allocation, it only changes in the definition

    double *capacidade;
    /* ... */
    capacidade = malloc(200 * sizeof *capacidade); // usa o tipo do objecto
    /* ... */
    free(capacidade);
    
17.04.2016 / 13:00