Do I cast the result of malloc?

Viewed 320265

In this question, someone suggested in a comment that I should not cast the result of malloc. i.e., I should do this:

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

rather than:

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

Why would this be the case?

29 Answers

TL;DR

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

has two problems. The cast and that you're using the type instead of variable as argument for sizeof. Instead, do like this:

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

Long version

No; you don't cast the result, since:

  • It is unnecessary, as void * is automatically and safely promoted to any other pointer type in this case.
  • 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 bad.
  • It can hide an error if you forgot to include <stdlib.h>. This can cause crashes (or, worse, not cause a crash until way later in some totally different part of the code). Consider what happens if pointers and integers are differently sized; then you're hiding a warning by casting and might lose bits of your returned address. Note: as of C99 implicit functions are gone from C, and this point is no longer relevant since there's no automatic assumption that undeclared functions return int.

As a clarification, note that I said "you don't cast", not "you don't need to cast". In my opinion, it's a failure to include the cast, even if you got it right. There are simply no benefits to doing it, but a bunch of potential risks, and including the cast indicates that you don't know about the risks.

Also note, as commentators point out, that the above talks about straight C, not C++. I very firmly believe in C and C++ as separate languages.

To add further, your code needlessly repeats the type information (int) which can cause errors. It's better to de-reference the pointer being used to store the return value, to "lock" the two together:

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

This also moves the length to the front for increased visibility, and drops the redundant parentheses with sizeof; they are only needed when the argument is a type name. Many people seem to not know (or ignore) this, which makes their code more verbose. Remember: sizeof is not a function! :)


While moving length to the front may increase visibility in some rare cases, one should also pay attention that in the general case, it should be better to write the expression as:

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

Since keeping the sizeof first, in this case, ensures multiplication is done with at least size_t math.

Compare: malloc(sizeof *sieve * length * width) vs. malloc(length * width * sizeof *sieve) the second may overflow the length * width when width and length are smaller types than size_t.

In C, you don't need to cast the return value of malloc. The pointer to void returned by malloc is automagically converted 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. Especially pointer casts.

As others stated, it is not needed for C, but necessary for C++. If you think you are going to compile your C code with a C++ compiler, for whatever reasons, 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++.

In C you can implicitly convert a void pointer to any other kind of pointer, so a 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.

In C you get an implicit conversion from void * to any other (data) pointer.

This question is subject of opinion-based abuse.

Sometimes I notice comments like that:

Don't cast the result of malloc

or

Why you don't cast the result of malloc

on questions where OP uses casting. The comments itself contain a hyperlink to this question.

That is in any possible manner inappropriate and incorrect as well. There is no right and no wrong when it is truly a matter of one's own coding-style.


Why is this happening?

It's based upon two reasons:

  1. This question is indeed opinion-based. Technically, the question should have been closed as opinion-based years ago. A "Do I" or "Don't I" or equivalent "Should I" or "Shouldn't I" question, you just can't answer focused without an attitude of one's own opinion. One of the reason to close a question is because it "might lead to opinion-based answers" as it is well shown here.

  2. Many answers (including the most apparent and accepted answer of @unwind) are either completely or almost entirely opinion-based (f.e. a mysterious "clutter" that would be added to your code if you do casting or repeating yourself would be bad) and show a clear and focused tendency to omit the cast. They argue about the redundancy of the cast on one side but also and even worse argue to solve a bug caused by a bug/failure of programming itself - to not #include <stdlib.h> if one want to use malloc().


I want to bring a true view of some points discussed, with less of my personal opinion. A few points need to be noted especially:

  1. Such a very susceptible question to fall into one's own opinion needs an answer with neutral pros and cons. Not only cons or pros.

    A good overview of pros and cons is listed in this answer:

    https://stackoverflow.com/a/33047365/12139179

    (I personally consider this because of that reason the best answer, so far.)


  1. One reason which is encountered at most to reason the omission of the cast is that the cast might hide a bug.

    If someone uses an implicit declared malloc() that returns int (implicit functions are gone from the standard since C99) and sizeof(int) != sizeof(int*), as shown in this question

    Why does this code segfault on 64-bit architecture but work fine on 32-bit?

    the cast would hide a bug.

    While this is true, it only shows half of the story as the omission of the cast would only be a forward-bringing solution to an even bigger bug - not including stdlib.h when using malloc().

    This will never be a serious issue, If you,

    1. Use a compiler compliant to C99 or above (which is recommended and should be mandatory), and

    2. Aren't so absent to forgot to include stdlib.h, when you want to use malloc() in your code, which is a huge bug itself.


  1. Some people argue about C++ compliance of C code, as the cast is obliged in C++.

    First of all to say in general: Compiling C code with a C++ compiler is not a good practice.

    C and C++ are in fact two completely different languages with different semantics.

    But If you really want/need to make C code compliant to C++ and vice versa use compiler switches instead of any cast.

    Since the cast is with tendency declared as redundant or even harmful, I want to take a focus on these questions, which give good reasons why casting can be useful or even necessary:


  1. The cast can be non-beneficial when your code, respectively the type of the assigned pointer (and with that the type of the cast), changes, although this is in most cases unlikely. Then you would need to maintain/change all casts too and if you have a few thousand calls to memory-management functions in your code, this can really summarizing up and decrease the maintenance efficiency.

Summary:

Fact is, that the cast is redundant per the C standard (already since ANSI-C (C89/C90)) if the assigned pointer point to an object of fundamental alignment requirement (which includes the most of all objects).

You don't need to do the cast as the pointer is automatically aligned in this case:

"The order and contiguity of storage allocated by successive calls to the aligned_alloc, calloc, malloc, and realloc functions is unspecified. The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated)."

Source: C18, §7.22.3/1


"A fundamental alignment is a valid alignment less than or equal to _Alignof (max_align_t). Fundamental alignments shall be supported by the implementation for objects of all storage durations. The alignment requirements of the following types shall be fundamental alignments:

— all atomic, qualified, or unqualified basic types;

— all atomic, qualified, or unqualified enumerated types;

— all atomic, qualified, or unqualified pointer types;

— all array types whose element type has a fundamental alignment requirement;57)

— all types specified in Clause 7 as complete object types;

— all structure or union types all of whose elements have types with fundamental alignment requirements and none of whose elements have an alignment specifier specifying an alignment that is not a fundamental alignment.

  1. As specified in 6.2.1, the later declaration might hide the prior declaration."

Source: C18, §6.2.8/2

However, if you allocate memory for an implementation-defined object of extended alignment requirement, the cast would be needed.

An extended alignment is represented by an alignment greater than _Alignof (max_align_t). It is implementation-defined whether any extended alignments are supported and the storage durations for which they are supported. A type having an extended alignment requirement is an over-aligned type.58)

Source. C18, §6.2.8/3

Everything else is a matter of the specific use case and one's own opinion.

Please be careful how you educate yourself.

I recommend you to read all of the answers made so far carefully first (as well as their comments which may point at a failure) and then build your own opinion if you or if you not cast the result of malloc() at a specific case.

Please note:

There is no right and wrong answer to that question. It is a matter of style and you yourself decide which way you choose (if you aren't forced to by education or job of course). Please be aware of that and don't let trick you.


Last note: I voted to lately close this question as opinion-based, which is indeed needed since years. If you got the close/reopen privilege I would like to invite you to do so, too.

The casting of malloc is unnecessary in C but mandatory in C++.

Casting is unnecessary in C because of:

  • void * is automatically and safely promoted to any other pointer type in the case of C.
  • It can hide an error if you forgot to include <stdlib.h>. This can cause crashes.
  • If pointers and integers are differently sized, then you're hiding a warning by casting and might lose bits of your returned address.
  • If the type of the pointer is changed at its declaration, one may also need to change all lines where malloc is called and cast.

On the other hand, casting may increase the portability of your program. i.e, it allows a C program or function to compile as C++.

The main issue with malloc is to get the right size.

The memory returned form malloc() is untyped, and it will not magically gain an effective type due to a simple cast.

I guess that both approaches are fine and the choice should depend on programmer intention.

  1. If allocating memory for a type, then use a cast.

ptr = (T*)malloc(sizeof(T));

  1. If allocating memory for a given pointer, then don't use a cast.

ptr = malloc(sizeof *ptr);

Ad 1

The first method assures the correct size by allocating memory for a given type, and then casting it to assure that it is assigned to the right pointer. If incorrect type of ptr is used then the compiler will issue a warning/error. If the type of ptr is changed, then the compiler will point the places where the code needs refactoring.

Moreover, the first method can be combined into a macro similar to new operator in C++.

#define NEW(T) ((T*)malloc(sizeof(T)))
...
ptr = NEW(T);

Moreover this method works if ptr is void*.

Ad 2

The second methods does not care about the types, it assures the correct size by taking it from the pointer's type. The main advantage of this method is the automatic adjustment of storage size whenever the type of ptr is changed. It can save some time (or errors) when refactoring.

The disadvantage is that the method does not work if ptr is void* but it may be perceived as a good thing. And that it does not work with C++ so it should not be used in inlined functions in headers that are going to be used by C++ programs.

Personally, I prefer the second option.

For me, the take home and conclusion here is that casting malloc in C is totally NOT necessary but if you however cast, it wont affect malloc as malloc will still allocate to you your requested blessed memory space. Another take home is the reason or one of the reasons people do casting and this is to enable them compile same program either in C or C++.

There may be other reasons but other reasons, almost certainly, would land you in serious trouble sooner or later.

Related