Monday, April 25, 2011

Do I cast the result of malloc?

In this question, someone suggested in a comment that I should not cast the results of malloc. I.e.

int *sieve = malloc(sizeof(int)*length);

rather than

int *sieve = (int *)malloc(sizeof(int)*length);

Why would this be the case?

From stackoverflow
  • In C you get an implicit cast from void* to any other (data) pointer.

  • It's optional. Typically you do the cast to avoid compiler warnings.

    Marco

    dreamlax : You won't get a warning because a void pointer can always be cast to any other pointer.
    Lars Wirzenius : Thus, if you get a warning without the cast, your code has a bug, probably not including .
    quinmars : Or he has an ancient libc version, where malloc returns a (char *)-pointer: http://en.wikipedia.org/wiki/Malloc
  • In C, you don't need to cast the return value of malloc. The pointer to void returned by malloc is automagically cast to the correct type. However, if you want your code to compile with a C++ compiler, a cast is needed. A preferred alternative among the community is to use the following:

    int *sieve = malloc(sizeof *sieve * length);
    

    which additionally frees you from having to worry about changing the right-hand side of the expression if ever you change the type of sieve.

    Casts are bad, as people have pointed out. Specially pointer casts.

    Thomas L Holaday : In the preferred alternative, what is "a" ?
    dirkgently : Typo. Thanks though!
  • You don't cast the result, since:

    • It is unnecessary, as void * is automatically and safely promoted to any other pointer type.
    • It can hide an error, if you forgot to include <stdlib.h>.
    • It adds clutter to the code, casts are not very easy to read (especially if the pointer type is long).
    • It makes you repeat yourself, which is generally a badness.
    jalf : True. However, in C++ the cast is required, so if you want your code to work in both, you'll have to compromise. But in pure C, don't do the cast for the reasons you stated.
    Jonathan Leffler : Agreed with @jalf. My code normally compiles under C or C++ compilers, even though it is primarily C. I sometimes use /*=C++=*/ comments to indicate why the cast is present.
    Matt Joiner : amen for a straight C answer, none of this C++ nonsense
  • In C you can implicitly cast a void pointer to any other kind of pointer, so an explicit cast is not necessary. Using one may suggest to the casual observer that there is some reason why one is needed, which may be misleading.

  • As other stated, it is not needed for C, but for C++. If you think you are going to compile your C code with a C++ compiler, for which reasons ever, you can use a macro instead, like:

    #ifdef __cplusplus
    # define NEW(type, count) ((type *)calloc(count, sizeof(type)))
    #else
    # define NEW(type, count) (calloc(count, sizeof(type)))
    #endif
    

    That way you can still write it in a very compact way:

    int *sieve = NEW(int, 1);
    

    and it will compile for C and C++.

    Hosam Aly : Since you're using a macro anyway, why don't you use `new` in the definition of C++?
    quinmars : Because there is no reason to do so. It is mainly for C programs that are compiled with a C++ compiler. If you are going to use 'new', the only thing you get are problems. You need then also a macro for free. And you need a macro to free an array, a differentiation that doesn't exists in C.
    quinmars : Not to mention if it's not you who frees the memory but maybe a C library you are using, etc. Many possible problems without any gain.
    Hosam Aly : Hmmm... I didn't think of that. Is it an error to use `free()` to free memory allocated with `new`?
    quinmars : Heh, I always thought so, but I'm not 100% sure. Maybe a good SO-question :)
  • I like this explanation because it's throughout, talking about possible goodness and bad consequences: Casting.

  • This is kind of off topic, but a lot of people here I think are being a little harsh on casting. There are perfectly legitimate reasons to do it, like the following:

    int x = 1;
    int y = 2;
    double z;
    z = (double) x / (double) y;
    

    Lest we forget our painful integer division bugs!

    David Cournapeau : It was about casting the return of malloc. Of course, casting is sometimes necessary - but casting in C should not be done lightly. It can hide a lot of bugs, and explicit cast bypass the C system (C is nothing more than a typed assembler after all :) ).

0 comments:

Post a Comment

Note: Only a member of this blog may post a comment.