Is malloc typecast recommended?

Asked

Viewed 747 times

8

I have read that it is not advisable to do the Typecast of 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 it is not recommended to do the Typecast of malloc?
  • What kind of complications can this practice bring to my program?

An example with and without the 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;
}

3 answers

7


As many authors and as written in the article C-Faq Malloc Cast, everyone says that the typecast in C, 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 where the Typecast it will still be necessary.

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 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 holds the values [244] [1] [0] [0].

c is a vector of 4 bytes.

n has the size of 4 bytes just like c

When to assign c for n, 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 this.

Some languages like Java and C++ would not allow this assignment, as they are different types. And that’s where the Typecast

n = (int *) c;

This prevents the compiler from sending a warning of different types of variables. And this is exactly what happens when using the malloc. The return void * is just being treated as int *, char *, or which you are using.

Completion:

It’s not like the Typecast is not recommended or feasible, is not necessary (at times). Use the Typecast to pass values of float for int, and unsigned for signed is used and does not use it, may end up bringing problems to your code, but can also mask some errors like difference in size 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

4

It is not really recommended to perform Typecast, at least in C. The malloc return is in its essence 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 can come to mask problems that the compiler could ideally identify.

More information on the C-FAQ http://c-faq.com/malloc/cast.html

4

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);

Browser other questions tagged

You are not signed in. Login or sign up in order to post.