Is Typecast from malloc recommended?

I have already read about it that it is not recommended to do the typecast of the malloc when we are allocating memory to a new pointer variable, and many websites and books teach this practice in memory allocation, it left me with some doubts.

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

An example with and without the typecast do 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;
}
Author: gato, 2016-04-13

3 answers

As well as many authors and as it is written in the Article C-Malloc cast faq, everyone says that the typecast in C, it is not necessary, and due to automatic treatment of types void * for other types, then suggest not to make use of it, but there are cases when the typecast will still be needed.

What is the purpose of typecast?

The typecast serves only to make a pseudo conversion. This means that the value of the variable is not converted, but rather 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 save values [244] [1] [0] [0].

c is a vector of 4 bytes.

n it has the size of 4 bytes as well as c

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

Some languages like Java and C++ would not allow this assignment, as they are different types. And that's where typecast{[29 comes in]}

n = (int *) c;

This prevents the compiler from sending an alert of different types of variables. And that's exactly what happens when you use malloc. The return void * is only being treated as int *, char *, or the one you're using.

Conclusion:

It is not as if the typecast was not recommended and not feasible, it is not necessary (on certain occasions). Using typecast to pass values from float to int, and unsigned to signed is used and not using it, can end up bringing problems to your code, but it can also mask some errors such as difference in size of structures and things like that, but are some problems caused by carelessness of developer.

References:

C-fac

Typecast in C SO

Typecast is necessery

Pontov

TIExpert

 6
Author: Brumazzi DB, 2017-05-23 12:37:33

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

As complications, I say from experience, the use of typecasts in C can mask problems that the compiler could ideally identify.

More information, in C-FAQ http://c-faq.com/malloc/cast.html

 3
Author: Jean Vitor, 2016-04-13 22:07:28

It is not recommended to cast to the result of malloc() for the compiler to indicate the error of missing #include <stdlib.h>.

Since the compiler has no information about the result type of malloc() it assumes that this function returns a value of type int. After

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

The explicit conversion converts this int (at this point you have already invoked UB, since you are treating the returned value as if it were a different type than it actually is) into a 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 (invalid) value of type int * is assigned to variable.

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


More notes

Sem #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. In addition, the explicit conversion of this int to int * is invalid, but since it was an explicit request from the programmer, the compiler does not complain.

1B Red redundancy

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

2A Erro error and redundancy

In the first case we have a value of type void* returned by the malloc() interpreted as int because of the absence of the correct header. After that we have the redundancy of asking the conversion of int into int. The following is the assignment of a type value int the 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 the conversion of the result. Assigning a int to a int * is wrong.

2B {error

As in 2a, the error does not have to do with the use of malloc() or the conversion of the returned value.

3A {error that the compiler complains about and easily fixes itself

When the compiler complaint of assigning a value of type int to a variable of type int * (the gcc has an misleading text for this spicific error), the programmer notices that he missed the inclusion of the header <stdlib.h>.

3B OK OK

Correct way to use malloc().


Plus 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 someone remembers that it will be it is 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, only changes in the definition

    double *capacidade;
    /* ... */
    capacidade = malloc(200 * sizeof *capacidade); // usa o tipo do objecto
    /* ... */
    free(capacidade);
 3
Author: pmg, 2020-06-11 14:45:34