2766

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?

Patrick McDonald
  • 64,141
  • 14
  • 108
  • 120
  • 35
    http://stackoverflow.com/q/7545365/168175 – Flexo Jan 15 '12 at 20:06
  • 7
    Casts are evil. I see so many cast in code just as a result of bad coding practice. Whenever you need to insert one the first thing you should ask yourselves is " what is wrong here" . Is everything declared as it should be ? If it is no cast would be needed so something is declared wrong. If you really do need to do some low level stuff on individual bytes in an int or so consider a union to access them. That'll declare them just fine. As a rule of thumb do not insert them unless the compiler complains. Then avoid them. This example will not complain. void pointer will promote to any type. – Hans Lepoeter Feb 21 '21 at 21:52
  • 2
    @HansLepoeter in C++ , those are necessary for malloc, giving some basis to my notion that there's something wrong with it – An Ant Feb 27 '21 at 11:51
  • 4
    @AnAnt C++ is not C. Their type systems are totally different. Observations about C++'s type system do not necessarily apply to C. In fact, they rarely do. – Braden Best Oct 14 '22 at 06:23
  • Would you consider casting to a baseclass (in C) consider wrong? – caulder Jun 21 '23 at 16:49
  • @caulder "casting to a baseclass in C"--good luck with that! Hint: What's the name of C with classes? – Karoly Nyisztor Jul 18 '23 at 15:28

29 Answers29

2513

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.

klutt
  • 30,332
  • 17
  • 55
  • 95
unwind
  • 391,730
  • 64
  • 469
  • 606
  • 62
    Please consider updating the answer. The cast is no longer dangerous, and repeating oneself is not necessarily a bad thing (redundancy can help catch errors). – n. m. could be an AI Dec 08 '16 at 12:30
  • 33
    Compilers have changed. An up-to-date compiler will warn you about a missing declaration of malloc. – n. m. could be an AI Dec 08 '16 at 12:40
  • 102
    @n.m. Ok. I think it's bad to assume that anyone reading here has a particular compiler. Also, since C11 the entire "implicit function" concept is gone, I didn't know that. Still, I don't see the point in adding a pointless cast. Do you also do `int x = (int) 12;` just to make things clear? – unwind Dec 08 '16 at 12:48
  • 6
    I've encountered a case where redundancy of the malloc cast helped to find a bug. This doesn't happen often but still. – n. m. could be an AI Dec 08 '16 at 13:10
  • 2
    When using sizeof with a specific type, I like to separate sizeof and (type) with a single space (I.e. `sizeof (int)`) just to reinforce that the argument to sizeof is `(int)`, not `int` – Braden Best Dec 17 '16 at 18:02
  • 51
    @n.m. if explicitly casting a void pointer "helped" solve a bug, you more likely encountered undefined behavior, which would mean the program in question likely has a far worse, undiscovered bug that you haven't run into yet. And one day, on a cold winter evening, you'll come home from work to find your GitHub page flooded with issue reports complaining about demons flying out of the users' noses – Braden Best Dec 17 '16 at 18:49
  • 3
    @BradenBest No, this is not the case, even remotely so. You can look at the program in question [here](http://stackoverflow.com/questions/40854155/dynamic-allocation-of-2d-array-function/40854925#40854925). – n. m. could be an AI Dec 17 '16 at 20:30
  • 36
    @unwind Even I agree with you, `(int)12` is not comparable. `12` *is* an `int`, the cast does simply nothing. The retval of `malloc()` is `void *`, not the pointer type casted to. (If it is not `void *`. So the analogy to `(int)12` would be `(void*)malloc(…)` what nobody is discussing.) – Amin Negm-Awad Jan 08 '17 at 04:30
  • 12
    "I think it's bad to assume that anyone reading here has a particular compiler. Also, since C11 the entire "implicit function" concept is gone, I didn't know that" - It's gone since C99 (not just C11). Any C99 compiler is *required* to issue a diagnostic if `#include ` isn't included.Out of the 4 bullets, the first 3 are subjective (there's sufficient proof that some tend to favor it in this page) and the 4th has been "fixed" in C language about 10 years before this answer. While I am not advocating in favor of the cast, it's really a case of *making a mountain out of a mole* here. – P.P Jan 18 '17 at 12:50
  • 9
    @unwind comparing with `double d = (double)12;` or `unsigned int u = (unsigned int)12;` might make more sense. – Ryan Haining Mar 03 '17 at 19:08
  • 2
    "the second may overflow the length * width when width and length are smaller types that size_t." - I don't get this. I thought the variables get promoted to larger type. How is the overflow possible? – Nguai al May 11 '17 at 06:08
  • 3
    how comes the compiler is throwing warnings _unless_ i cast the result of malloc? – Gewure May 29 '17 at 11:24
  • 2
    @Nguaial No, promotion has nothing to do with the type of the left-hand side of an assignment. This is a common misconception. `double a = 1 / 2;` is `0` since it's an integer division. – unwind May 30 '17 at 08:51
  • 7
    @Gewure Obviously quite hard to answer without your code, but probably because you're failing to `#include ` for `malloc()`'s prototype, thus making the compiler assume it returns `int`, which you can't assign to a pointer without a cast. The cast is not enough, in that case. – unwind May 30 '17 at 08:52
  • 3
    Not reviewing ALL allocations in the code when changing a data type size/switching to a different data type is asking for troubles. you can use casting to your an advantage to quiclky find all malloc calls for a certain type. – Michaël Roy Jun 17 '17 at 21:57
  • Let's say we have C++ project and C library file where header has `extern "C"...` setup. When compiler compiles .c file, will it work if there is no casting of `malloc`, because we are in C++ project? – unalignedmemoryaccess Jun 29 '17 at 06:27
  • @tilz0R Yes, of course. The `extern "C"` is for the C++ compiler, it just tells it not to name-mangle when looking for the C function. The C function is built by a C compiler and is written in C. – unwind Jun 29 '17 at 08:04
  • So then I don't know why we always *fight* over *you cannot write C and C++ code for the same project*. I'm using `extern "C"` approach in every my C library so then it is allowed to not cast `malloc` and will still compile. Case closed for me then. I'm not casting it anymore then if this is really *hidden* error if you cast result. In general to me, your 4th point why not cast has no sense, or at least I don't get it. If non NULL is returned, memory is allocated, you can cast it how you want. – unalignedmemoryaccess Jun 29 '17 at 08:06
  • 1
    @tilz0R Pre-C11, functions without prototype were assumed to return `int`. But `int` is often smaller than `void *` (32 vs 64 bits), so doing `foo *x = (foo *) malloc(sizeof *x);` might have hidden a warning caused by making the (undeclared, assumed `int`) return value from `malloc()` be treated as a pointer, when it in fact is not large enough and thus won't work. – unwind Jun 29 '17 at 08:13
  • 6
    @unwind "*Pre-C11, functions without prototype were assumed to return int*" <- this was already gone in C99. –  Aug 16 '17 at 12:30
  • 2
    @unwind, actually, I think that point which you say is no longer relevant is still relevant because if you try to compile code without specifying `--std=c11` (as many do), you'll get but a mere warning... In fact, even when specifying `--std=c11` I get "warning: implicit declaration of function ‘malloc’", when I've not included the standard library header for it. This isn't an uncommon implementation, either; gcc version 5.4.0 20160609... – autistic Sep 07 '17 at 16:46
  • @unwind There's room for misinterpretation there; some users might think this means "this point is no longer relevant, since it just emits a warning and (*erroneously*) we can ignore the warning". – autistic Sep 08 '17 at 07:53
  • 3
    "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" I don't understand what overflow can happen here. – savram Sep 10 '17 at 02:28
  • 4
    @savram If `length` and `width` are `int`s, where `int` has fewer bits than `size_t`, then `length*width` might be bigger than the largest `int`. This is less likely to be an issue if you use `size_t` math, which you can do by putting the `sizeof` part first (since the compiler “reads” multiplications from left to right) – Daniel H Sep 19 '17 at 22:10
  • @DanielH Thank you, I understand about the int now. But why changing the order solves anything? What if the multiplication of sizeof * length exceeds the largest sizeof? – savram Sep 20 '17 at 01:45
  • 1
    @savram The `malloc` function takes a `size_t` as input. If the whole multiplication exceeds that, then you just can't do the allocation you want. This is unlikely in a bug-free program, because on most 64-bit systems that would be asking for 18 *exabytes* of memory, more than I think has actually been manufactured ever. On the other hand, the maximum `int` on such systems is often 2^31-1, or just over two gigabytes; a lot of programs would want to allocate that much. – Daniel H Sep 20 '17 at 14:57
  • @DanielH I'd suggest that the bigger problem there is... why was `int` chosen as the type for `length` and `width`? We should take care in choosing types for our variables, and unless it absolutely makes sense for a length and/or width to be negative, all signed options should be discarded from the choices. After all, you wouldn't want a two-dimensional array where each dimension can have *negative* indices, right? That's just begging for undefined behaviour. Wouldn't you rather suggest that `length` and `width` be refactored as `size_t`, to avoid further complications? – autistic Feb 25 '18 at 04:11
  • @Sebivor It depends on the context. Sometimes there are reasons for using `signed` types anyway, and more often `length` might be unsigned but smaller than `size_t` for some reason. I agree that, all else being equal, it's better if `length` is a `size_t`. I was also answering savram's question about how an overflow could happen with `length * width * sizeof *sieve`, as mentioned in the question; just saying to always make `length` and `width` be of type `size_t` would not be an answer. – Daniel H Feb 25 '18 at 13:31
  • 3
    Regarding sizeof() vs sizeof: yes, it's not a function, but it behaves somewhat like a function (or more accurately a macro I suppose). And also () makes it clear to anyone reading EXACTLY what size you're taking. Personally I feel strongly that the ability to leave off the paren's is a bug, not a feature. @Kevin: this is why you use `sizeof(*x)`, as mentioned in the answer. – DimeCadmium Jun 27 '18 at 18:15
  • 12
    *I very firmly believe in C and C++ as separate languages.* => You shouldn't be firm about things that fly in the face of both history and present practice. C++ didn't inherit C's syntax because of its intrinsic beauty; it was so that C codebases can incrementally adopt C++ features. Plus, there's a lot of value in being *able* to compile a C codebase with a C++ compiler whether that's how you ultimately ship your binary or not, see the [C++ core guidelines](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-cpl). One can write a lot of neat type_traits-based static checks for C. – HostileFork says dont trust SE Jul 30 '18 at 14:04
  • 4
    @HostileFork That may have been true back when C++ was just a plain preprocessor on top of C, with a solid philosophy guiding the language. But in the past couple of decades, syntactic creep has left it nearly unrecognizable as a dialect of C. A lot of compliant C code refuses to compile with a C++ compiler (try creating a struct named 'template' with a field named 'class'). Meanwhile the ISO C++ committee has neglected to keep up with modern developments to the ISO C standards, leaving the languages on two separate tracks: one promising portability, and the other boasting flexibility. – Ryan Jan 10 '19 at 05:07
  • 3
    @HostileFork @Ryan You don't even have to use C++ keywords to get C/C++ incompatibility: I recently had a problem when I first used C++ because the library I used (OpenCV) was being deprecated in C (WTF!), and the only stable option was to use C++. When I tried to use my C library which includes functions like this one `void foo(int n, int arr[n])`, I realized C++ doesn't allow that, which I think is really stupid (tell me otherwise), and then I decided to do separate headers for C (.h) and for C++ (.hpp) (both referring to C code), even if that means repeating most of the code in the headers. – alx - recommends codidact Jan 30 '19 at 18:41
  • -1 Where/how are you getting "keeping the sizeof first, in this case, ensures multiplication is done with at least `size_t` math"? Pretty sure the standard arithmetic conversions are order-independent. I'll switch to +1 if you remove that claim or clarify that you mean something more nuanced or convince me I'm mistaken. – mtraceur Dec 06 '19 at 21:34
  • 2
    I think maybe this idea grew out of the fact that order *does* make a difference in expressions with more than one operation? For example, the order does make a difference in `sizeof foo * bar * qux` vs `bar * qux * sizeof foo`, because the standard arithmetic conversions are local to each operator's arguments instead of being done across the entire expression. That's actually a very good point to warn people about, but we should do it with wording that accurately explains that, whereas the current wording suggests that order matters even in just `size foo * bar` vs `bar * sizeof foo`. – mtraceur Dec 06 '19 at 21:42
  • Great, comprehensive answer otherwise, to be clear. Would've been an immediate +1 were it not for the above. – mtraceur Dec 06 '19 at 21:46
  • 1
    When I changed `arr = (Array *)malloc(sizeof(Array))` to `arr = malloc(sizeof arr)` my program started crashing, and changing it back fixed the problem, so I've decided to stick with the unpopular casting approach. – mathematrucker Dec 19 '19 at 04:11
  • 4
    @mathematrucker uh, you changed the size of your allocation from `sizeof(Array)` to `sizeof arr`. The latter is the size of a pointer, not the size of your structure, so of course your program started crashing. – nneonneo Feb 06 '20 at 10:28
  • @nneonneo thanks I don't remember exactly what my code was now (I changed it for the comment) but I see what you're saying maybe I just needed to dereference. – mathematrucker Feb 07 '20 at 23:36
  • I'm used to writing `int* sieve` rather than `int *sieve`. When writing the `sizeof *sieve` part, would it be the same if I wrote `sizeof* sieve`? Am I even using a healthy convention? – Matt Apr 26 '20 at 20:29
  • 1
    @Matt Yes, it would be the same. Whether or not your convention is healthy or not is probably cause for enough religious wars. I personally don't use it, since it makes things like `int* a, b` very confusing, basically you're trying to shape the syntax into something it is not which I find confusing. Of course you could *also* have a convention never to declare more than variable per declaration (and have another war around that) but *I* find that wasteful. :) Sorry for not being definitive. – unwind Apr 27 '20 at 08:18
  • 1
    When you write `int *sieve = malloc(length * sizeof *sieve);` you are "needlessly" repeating the name of the object (`sieve`) and violating the DRY principle. So why is this better than repeating the `int`? – Chris Dodd Dec 12 '20 at 20:25
  • @ChrisDodd variable name are mean to be reuse not type of one variable. – Stargateur Dec 13 '20 at 05:59
  • 3
    `sizeof(*sieve) * length` is more readable, and not only is `sizeof *sieve * length` just plain silly, it is _purely_ a subjective call to make. Also, you have a Black & White fallacy in your implied argument. Would you write `a = b * 2 + c` if you want `a` to equal `b * (2 + c)`? Is `b *` a function? Of course not. We don't use parentheses only for functions, they have many other uses. – SO_fix_the_vote_sorting_bug Jan 13 '21 at 18:11
  • since C99 one can write `malloc(sizeof(int[length]))` – tstanisl Apr 07 '21 at 16:13
  • @tstanisl since C11 one can't anymore (And that good) – Stargateur Apr 07 '21 at 17:09
  • @Stargateur I do not think it's good. I understand issues with automatic VLAs but what's wrong with VM types? – tstanisl Apr 07 '21 at 17:55
  • 1
    The argument that "*keeping the `sizeof` first, in this case, ensures multiplication is done with at least `size_t` math*" is completely bogus. The order of the operands of a `*` operator does not affect the result of applying the usual arithmetic conversions to them, and *that's* ultimately what determines the data type for the operation and result. Personally, I find it easier to read the version with the `sizeof` second. – John Bollinger Feb 03 '22 at 14:49
  • 1
    Oh c'mon how can you forget to include stdlib.h and **not** have thousands of other warnings in your code? This is a bogus argument. It's not the lack of cast that will save you. There will be lots of undeclared macros and functions to trigger that warning. Unless your code is a single line calling malloc with a very old compiler that still accepts implicit declarations. – marcus Mar 24 '22 at 22:18
  • The suggested idea (for the 1st problem) is bad because C's lack of difference of the notion of _a call to an allocation function_ (to get a plain `void*` value) and _an allocation of an object_ (to get a pointer value to an allocated object) as different intentional uses (like [this answer](https://stackoverflow.com/a/70740380/2307646)), which cause serious confusion in resource management. – FrankHB May 13 '22 at 07:43
  • Unfortunately C has neither function templates nor `new`-expressions like in C++. Despite to interoperation to C++ or function prototyping (and irrelevant to the version of C), this lack of the expressive forms is a real defect of C (at least as a statically typed language), and it is occasionally hidden by coercion to `void*`, which is an instance of (obvious wrong use of) ad-hoc polymorphism. The ignorance in this point is widespread among C users (like in @unwind 's reply) and probably leads to bad resource management code in productions implemented in C. – FrankHB May 13 '22 at 07:44
  • It may still worth preventing the confusion in the cost of verbosity of the cast; albeit this is only a workaround to the C language. As of the 2nd problem (`sizeof`), it is both applicable in C and C++, hence inconsistent to the claim of "that the above talks about straight C, not C++" in the answer. – FrankHB May 13 '22 at 07:46
  • Note it is plausible to have the coercion in ancient C because of the some vague notions (e.g. object lifetime) in the object model, but since C99, the wording of _effective type_ makes the case clearer and more closer to C++. OTOH, in C++, the rules on object lifetime are still far stricter due to the "live" invariant being enforced (esp. with non-trivial ctor & dtor calls), so the traditional way in C is simply logically incorrect. C++ has other cost of the clarification (like `std::launder` and relocatable objects), but this is another story which is also not yet addressed in C. – FrankHB May 13 '22 at 08:01
  • In Arduino IDE, I got a warning because I didn't type cast the result of the malloc. With this `bool *state = malloc(sizeof(bool) * count);` then I used this and the warning is gone `bool *state = (bool*) malloc(sizeof(bool) * count);`, what you think ? – R1S8K Oct 21 '22 at 08:24
  • 1
    @R1S8K The Arduino is programmed in a language that is a "dialect" of C++, and compiled (after some source-level automatic changes, as far as I can understand) by a C++ compiler. So this answer, which is about C, does not apply. – unwind Nov 07 '22 at 08:23
  • @unwind Thanks, so `malloc` won't work the same in C++ as in C, is that right ? – R1S8K Nov 11 '22 at 06:52
  • 1
    @R1S8K The function works the same for sure, but C++ has other rules about automatic conversion of pointers of different types. They are more strict, basically. In C any data pointer automatically converts to/from `void *`, but in C++ that is not true. They are different languages, with different rules. – unwind Nov 11 '22 at 08:01
  • @unwind Thanks man. I'm starting off my C++ skills, I want to port a code to another library. I'm ok with functions overloading, setters, getters, a little of functions domain ... etc. It's an embedded graphics library. There's a function to allocate memory for the sprite `uint8_t* ptr8 = nullptr;` then `ptr8 = ( uint8_t*) ps_calloc(frames * w * h + frames, sizeof(uint16_t));` – R1S8K Nov 11 '22 at 08:08
480

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.

royhowie
  • 11,075
  • 14
  • 50
  • 67
dirkgently
  • 108,024
  • 16
  • 131
  • 187
  • 124
    @MAKZ I'd argue that `malloc(length * sizeof *sieve)` makes it look like `sizeof` is a variable - so I think `malloc(length * sizeof(*sieve))` is more readable. – Michael Anderson Apr 30 '15 at 07:02
  • 36
    And `malloc(length * (sizeof *sieve))` more readable still. IMHO. – Toby Speight Aug 20 '15 at 13:01
  • 25
    @Michael Anderson `()` issue aside, note that your suggested style switched the order., Consider when element count is computed like `length*width`, keeping the `sizeof` first in this case insures multiplication is done with at least `size_t` math. Compare `malloc(sizeof( *ptr) * length * width)` vs. `malloc(length * width * sizeof (*ptr))` - the 2nd may overflow the `length*width` when `width,length` are smaller types that `size_t`. – chux - Reinstate Monica Dec 10 '15 at 16:40
  • 3
    @chux it's not obvious, but the answer has been edited so that my comment is less pertinent - the original suggestion was `malloc(sizeof *sieve * length)` – Michael Anderson Dec 11 '15 at 00:18
  • 19
    C is not C++. Pretending that they are will ultimately lead to confusion and sadness. If you're using C++, then a C-style cast is also bad (unless you're using a very old C++ compiler). And `static_cast>()` (or `reinterpret_cast<>()` )is not compatible with any dialect of C. – David C. Feb 12 '16 at 23:12
  • 1
    @TobySpeight And I'd argue that `calloc(length, sizeof(*sieve))` is more readable than any of the alternatives I've seen proposed on this question. – Cubic Aug 27 '16 at 10:29
  • @Cubic Sure, but if you don’t need the memory zeroed it can be slower on some systems. – Daniel H Sep 19 '17 at 22:11
  • This is ugly, and not initialized. You need to use `calloc` and `sizeof()` – David 天宇 Wong Nov 26 '18 at 18:22
  • 2
    `int *sieve = reinterpret_cast(malloc(sizeof(*sieve) * length))` is *the best quality code* one can write, it was written by the gods of C++. – tripulse Aug 26 '20 at 06:05
  • 2
    In C++, the code smell is not from the cast, but from the use of malloc. You should not be using malloc at all in C++. Therefore, you shouldn't be casting the result. – William Pursell Oct 19 '21 at 12:49
  • Casts can be bad, but an implicit conversions should be even more evil when the only duty is to work around the lack of abstraction by breaking type safety. Here the implicit conversion, or *coercion*, is a case of ad-hoc polymorphism, because otherwise the values being converted are in different natural domain; while the C++ cast is just "normal" function invocation (and `Object*` -> `void*` is implicitly allowed because of *subtyping*). Abuse of polymorphism seems most smelly among these implicit or explicit conversions; and casts, when really needed, are not that bad. – FrankHB May 17 '22 at 21:22
  • 1
    @WilliamPursell It is true that `malloc` is smelly, but the problem still exists by replacing `malloc` to `::operator new`. It is not that bad in C++ because `::operator new` is more verbose than a plain `new` expression, so it looks like deliberated. (Using `new` expressions in C++ should be still blamed because they should be replaced by creations of plain objects/smart pointers/opaque pointers... as possible.) – FrankHB May 17 '22 at 21:27
407

You do cast, because:

  • It makes your code more portable between C and C++, and as SO experience shows, a great many programmers claim they are writing in C when they are really writing in C++ (or C plus local compiler extensions).
  • Failing to do so can hide an error: note all the SO examples of confusing when to write type * versus type **.
  • The idea that it keeps you from noticing you failed to #include an appropriate header file misses the forest for the trees. It's the same as saying "don't worry about the fact you failed to ask the compiler to complain about not seeing prototypes -- that pesky stdlib.h is the REAL important thing to remember!"
  • It forces an extra cognitive cross-check. It puts the (alleged) desired type right next to the arithmetic you're doing for the raw size of that variable. I bet you could do an SO study that shows that malloc() bugs are caught much faster when there's a cast. As with assertions, annotations that reveal intent decrease bugs.
  • Repeating yourself in a way that the machine can check is often a great idea. In fact, that's what an assertion is, and this use of cast is an assertion. Assertions are still the most general technique we have for getting code correct, since Turing came up with the idea so many years ago.
Ron Burk
  • 6,058
  • 1
  • 18
  • 20
  • 41
    @ulidtko In case you did not know, it's possible to write code which compiles both as C and as C++. In fact most header files are like this, and they often contain code (macros and inline functions). Having a `.c`/`.cpp` file to compile as both is not useful very often, but one case is adding C++ `throw` support when compiled with C++ compiler (but `return -1;` when compiled with C compiler, or whatever). – hyde Mar 26 '13 at 11:09
  • 42
    If someone had malloc calls inline in a header I wouldn't be impressed, #ifdef __cplusplus and extern "C" {} are for this job, not adding in extra casts. – paulm May 06 '13 at 17:55
  • 3
    Also nets you compatibility with compilers which compile C as C++ by default. (MSVC) – Jonathan Baldwin Jul 20 '13 at 00:28
  • 21
    Well, point 1 is irrelevant, since C != C++, the other points are also trivial, if you use _the variable_ in your `malloc` call: `char **foo = malloc(3*sizeof(*foo));` if quite full-proof: 3 pointers to char pointers. then loop, and do `foo[i] = calloc(101, sizeof(*(foo[i])));`. Allocate array of 101 chars, neatly initialized to zeroes. No cast needed. change the declaration to `unsigned char` or any other type, for that matter, and you're still good – Elias Van Ootegem Dec 23 '13 at 15:37
  • 12
    Casting will not hide an error - in fact it introduces the possibility for further errors (casting an int to pointer, most obviously) – Norwæ Apr 16 '14 at 11:10
  • 41
    When I tought I got it, there it comes! Fantastic answer. Its the first time here in StackOverflow that I +1 two opposite answers! +1 No, you dont cast, and +1 Yes, you do cast! LOL. You guys are terrific. And for me and my students, I made my mind: I do cast. The kind of errors students make are more easily spotted when casting. – DrBeco Sep 26 '14 at 03:22
  • 4
    Interesting that @Leushenko was the only commenter here to state the very important point that the casting is not DRY. IMHO that is a showstopper and why I do **not** cast in C. I suck it up in C++ because I have to. That said, "repeating yourself" does have its use: in unit tests. But certainly not in production code. Repeating oneself is just asking for trouble. I'm glad we can all agree to disagree but I can't see myself _ever_ being swayed by the casters' arguments. ;-) – Ray Toal Oct 18 '14 at 23:13
  • 6
    Maybe donotcasters could read this document: https://www.securecoding.cert.org/confluence/display/seccode/MEM02-C.+Immediately+cast+the+result+of+a+memory+allocation+function+call+into+a+pointer+to+the+allocated+type. I'm convinced that do not cast is more dangerous than casting and that casting the result of malloc is not "repeating yourself". – Jean-Baptiste Yunès Jan 27 '15 at 10:55
  • 6
    @Jean-BaptisteYunès: It's worth looking into comments below of this document. The rationale of `p = malloc(sizeof(gadget))` has little sense, as more idiomatic form would be just `p = malloc(sizeof *p)`. They didn't mention, that cast may be dangerous, producing nasty bugs, when `` header is not present (and C89 compilers are not obligated for any diagnostic in this case), as `malloc` is assumed to return an `int`. – Grzegorz Szpetkowski Feb 25 '15 at 22:22
  • 7
    So, do you also cast the argument of `free()` to `void *`? – Mohit Jain May 12 '15 at 05:27
  • 3
    @MohitJain That argument makes no sense. In Java, would you cast the argument of a method that takes `Object`? – PC Luddite Sep 02 '15 at 22:43
  • 19
    @Leushenko: Repeating yourself in a way that cannot be validated by machine nor by local inspection is bad. Repeating yourself in ways that can be validated by such means is less bad. Given `struct Zebra *p; ... p=malloc(sizeof struct Zebra);`, the malloc can't avoid duplciating information about p's type, but neither the compiler nor local code inspection would detect any problem if one type changed but the other didn't. Change the code to `p=(struct Zebra*)malloc(sizeof struct Zebra);` and the compiler will squawk if the cast type doesn't match `p`, and *local* inspection will reveal... – supercat Sep 18 '15 at 17:46
  • 5
    ...if the cast type doesn't match the `sizeof` type. Someone examining the version of code with the typecast can know that (if the code compiles cleanly) `p` is either `void*` or `struct Zebra*` without having to look at the actual declaration of `p`. To my mind that's a win. – supercat Sep 18 '15 at 17:49
  • 14
    "Repeating yourself in a way that the machine can check". No! If you leave out a cast (in general) you will get a warning if you do something unreasonable, or reasonable and not portable. If you use a cast, you say to the compiler: "Shut up! I've looked into it, and I know better.". Novices should not be taught the habit of putting up casts. malloc() is the one example where adding the cast does comparatively little harm. – Albert van der Horst Apr 01 '16 at 17:29
  • 5
    Great answer, thank you for it. Implicit conversions cause so many problems, and you do a good job of articulating why. Maybe reword the "stupendously stupid" part though? That would probably increase the chance of reaching people who don't already agree with you, rather than putting them on the defensive and making them unable hear the sensible things you're saying. – Don Hatch Nov 02 '16 at 08:31
  • 3
    @AlbertvanderHorst Novices should enable the compiler flag that turns implicit conversions into errors. – Tom Lint Nov 14 '16 at 15:18
  • 8
    Lots of fallacies in this answer. Basically, the only valid argument is the first one: cross-compilable C/C++ code. But it is only applicable to cross-compilable C/C++ code, not a reason to use the cast everywhere. The remaing arguments are fallacies based on the failure to undestand a simple fact: avoiding the cast is not a purpose in itself, but a part of wider idiomatic practice - writing type-independent/type-agnostic code. – AnT stands with Russia Jun 14 '17 at 15:45
  • 7
    Tha above reasoning tries to solve problems present in `T *p = malloc(N * sizeof(T))`. But you shouldn't do it this way in the first place. The proper idiomatic type-agnostic way to allocate memory calls for `T *p = malloc(N * sizeof *p)`, i.e. the type names are not mentioned in size expression at all. This version is completely free of any issues the above answer tries to "solve". In other words, explicit cast on the result of memory allocation function is a classc "solution looking for a problem". A problem you yourself created. Don't create the problem, and you won't need the solution. – AnT stands with Russia Jun 14 '17 at 15:48
  • Why do most of you say *casting is bad because if you cast an pointer as an integer you may lose bits depending on the platform* if the whole point **here** is regarding casting `void*` to an arbitrary but needed `T*`? – Luis Masuelli Apr 26 '18 at 16:33
  • 1
    Look the example, do not use a case: https://en.cppreference.com/w/c/memory/malloc – Kemin Zhou Nov 10 '18 at 17:00
  • 1
    @Jean-BaptisteYunès: The SEI reference for [MEM02-C: Immediately cast the result of a memory allocation function call into a pointer to the allocated type](https://wiki.sei.cmu.edu/confluence/display/c/MEM02-C.+Immediately+cast+the+result+of+a+memory+allocation+function+call+into+a+pointer+to+the+allocated+type) is at a new location (link valid today; who knows about tomorrow). – Jonathan Leffler Nov 19 '18 at 18:44
  • 2
    @Jean-BaptisteYunes: In your mentioned recommendation: MEM02-C-EX1: "Do not immediately cast the results of malloc() for code that will be compiled using a C90-conforming compiler because it is possible for the cast to hide a more critical defect (see DCL31-C. Declare identifiers before using them for a code example that uses malloc() without first declaring it). " – Michael Beer Nov 28 '19 at 17:14
  • +1 for "forest for the trees" comment. FFS, how many programmers would forget to `#include ` and then not figure it out when `malloc` isn't being called? It's like warning newbies of the pitfalls of forgetting to define a `main` function. "Whatever shall we do?! We cannot recover and it could remain a hidden bug for years!" Where do programmers pick up these absurd memes? – SO_fix_the_vote_sorting_bug Jan 13 '21 at 18:18
198

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 MALLOC(type) ((type *)malloc(sizeof(type)))
# define CALLOC(count, type) ((type *)calloc(count, sizeof(type)))
#else
# define MALLOC(type) (malloc(sizeof(type)))
# define CALLOC(count, type) (calloc(count, sizeof(type)))
#endif
# define FREE(pointer) free(pointer)

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

int *sieve = MALLOC(int); // allocate single int => compare to stack int sieve = ???;
int *sieve_arr = CALLOC(4, int); // allocate 4 times size of int => compare to stack (int sieve_arr[4] = {0, 0, 0, 0};
// do something with the ptr or the value
FREE(sieve);
FREE(sieve_arr);

and it will compile for C and C++.

Sinipelto
  • 147
  • 1
  • 8
quinmars
  • 11,175
  • 8
  • 32
  • 41
  • 22
    Since you're using a macro anyway, why don't you use `new` in the definition of C++? – Hosam Aly Mar 04 '09 at 06:13
  • 78
    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 Mar 04 '09 at 08:51
  • 9
    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. – quinmars Mar 04 '09 at 08:53
  • 4
    Hmmm... I didn't think of that. Is it an error to use `free()` to free memory allocated with `new`? – Hosam Aly Mar 04 '09 at 12:38
  • 96
    @Hosam: Yes, it definitely is. If you use `new` you must use `delete` and if you use `malloc()` you must you `free()`. Never mix them. – Graeme Perrow Jul 16 '11 at 17:10
  • Functions, variables, keywords and macros that only differ in case, though allowed, provide small differentiation. Maybe `CNEW(t, n)` – chux - Reinstate Monica Jun 07 '13 at 15:24
  • @chux, well, `new` is not a keyword in C and in a real C++ program I wouldn't use this macro at all, so no confusion. – quinmars Oct 25 '13 at 20:28
  • 24
    If one is going to take this approach, calling the macro `NEW` is probably a bad idea since the resource is never returned using `delete` (or `DELETE`) so you're mixing your vocabulary. Instead, naming it `MALLOC`, or rather `CALLOC` in this case, would make more sense. – mah Apr 16 '14 at 15:23
  • I'd be pretty unhappy seeing a #define used in this way. I guess if there's really no other option, it might be ok. But one day you're going to wish you hadn't done it. At least give the damn thing a better name than NEW. – Dave Branton Sep 29 '14 at 06:44
  • 1
    @DaveBranton, in what way do you see the use of `#define` critically? The macro does not alter any variable, the variable is only used once, it's a simple expression and not a sequence of statements. Plus, it cannot be done with a inline function. So I wonder what makes you worry. – quinmars Sep 29 '14 at 08:05
  • GLib ineed defines this macro. It calls it [g_new](https://developer.gnome.org/glib/stable/glib-Memory-Allocation.html#g-new), and [g_new0](https://developer.gnome.org/glib/stable/glib-Memory-Allocation.html#g-new0). – Niccolo M. Dec 31 '14 at 03:16
  • 1
    Actually it is much safer to add the cast in C if you use this macro. It will allow the compiler to catch this mistake: `long array = NEW_INT(int, n);` – chqrlie Feb 26 '15 at 19:57
  • 2
    Why to `#define` a new `NEW` if there is an old `new` operator in C++ ??? **malloc(3)** and **free(3)** are severely discouraged use functions from C in C++ (they are supported only for the claim of portability of C into C++). C++ encourages the use of `new` and `delete` operators instead. – Luis Colorado Apr 14 '15 at 05:22
  • 1
    is NEW a keyword in c++?. i guess not, and if i am right, the macro by @quinmars is quite a good solution. and there will be no troubles in using it. – milevyo Oct 12 '15 at 16:51
  • 3
    @LuisColorado This solution is for interop-style code between C and C++. It's not about doing things in a C++-idiomatic way, it's about making C code compile and port easily to a C++ compiler. –  Dec 13 '15 at 06:26
  • @quinmars One thing to note: When compiling with a C compiler, the provided code uses `calloc()` instead of `malloc()`, just because of the sake of symmetry between the two definitions. `malloc()` isn´t `calloc()`. `calloc()` *may* be slower when it initialises the zeros. On the other hand, it could be also more benefitial. But this is another question, see https://stackoverflow.com/q/1538420/12139179. But since the question is asked for `malloc()` I would rather do it like that: `#else #define NEW(type, count) (malloc(sizeof(type) * count))` – RobertS supports Monica Cellio Jan 11 '20 at 17:25
  • 1
    With your approach, the cast is actually useful in the C version to detect type mismatches such as: `long *sieve; ... ; sieve = NEW(int, 1);` – chqrlie May 19 '21 at 06:42
  • @quinmars There do exist differences in C's abstraction machine semantics but the code cannot reveal the behavioral differences since they can't contribute to observable behavior. However, if extensions allow things like non-trivial destructor calls on array elements, then there are definitely differences in the generated code. I suggest to adapt to the more complete mental model as C++ to avoid switching it back and forth. Any user ever caring about dtors/finalizers (almost always true with C and C++) shouldn't act as a compiler to do micro optimizations like trivial dtor DCE. – FrankHB May 13 '22 at 08:49
175

From the Wikipedia:

Advantages to casting

  • Including the cast may allow a C program or function to compile as C++.

  • The cast allows for pre-1989 versions of malloc that originally returned a char *.

  • Casting can help the developer identify inconsistencies in type sizing should the destination pointer type change, particularly if the pointer is declared far from the malloc() call (although modern compilers and static analyzers can warn on such behaviour without requiring the cast).

Disadvantages to casting

  • Under the ANSI C standard, the cast is redundant.

  • Adding the cast may mask failure to include the header stdlib.h, in which the prototype for malloc is found. In the absence of a prototype for malloc, the standard requires that the C compiler assume malloc returns an int. If there is no cast, a warning is issued when this integer is assigned to the pointer; however, with the cast, this warning is not produced, hiding a bug. On certain architectures and data models (such as LP64 on 64-bit systems, where long and pointers are 64-bit and int is 32-bit), this error can actually result in undefined behaviour, as the implicitly declared malloc returns a 32-bit value whereas the actually defined function returns a 64-bit value. Depending on calling conventions and memory layout, this may result in stack smashing. This issue is less likely to go unnoticed in modern compilers, as they uniformly produce warnings that an undeclared function has been used, so a warning will still appear. For example, GCC's default behaviour is to show a warning that reads "incompatible implicit declaration of built-in function" regardless of whether the cast is present or not.

  • 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.

Although malloc without casting is preferred method and most experienced programmers choose it, you should use whichever you like having aware of the issues.

i.e: If you need to compile C program as C++ (Although it is a separate language) you must cast the result of use malloc.

klutt
  • 30,332
  • 17
  • 55
  • 95
ashiquzzaman33
  • 5,781
  • 5
  • 31
  • 42
  • 3
    What does "_Casting can help the developer identify inconsistencies in type sizing should the destination pointer type change, particularly if the pointer is declared far from the `malloc()` call_" mean? Could you give an example? – Spikatrix May 14 '16 at 06:26
  • 4
    @CoolGuy: [See an earlier comment on another answer](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc?rq=1#comment53162479_14879184). But note that the `p = malloc(sizeof(*p) * count)` idiom picks up changes in the type automatically, so you don't have to get warnings and go change anything. So this isn't a real advantage vs. the best alternative for not-casting. – Peter Cordes Oct 24 '16 at 15:02
  • 11
    This is the proper answer: There are pros and cons, and it boils down to a matter of taste (unless the code must compile as C++ -- then the cast is mandatory). – Peter - Reinstate Monica Nov 15 '16 at 17:00
  • 4
    Point 3 is moot, since If the type of the pointer is changed at its declaration, one should check every instance of malloc, realloc and free inolving that type. Casting will force you to do just that. – Michaël Roy Jun 18 '17 at 01:46
  • 1
    If one forgets to include stdlib.h, and the program compiles, how does it link without a definition for malloc? If it links and runs anyway, which instructions actually get run on that line for any given CPU? I guess I should check godbolt... – SO_fix_the_vote_sorting_bug Aug 06 '21 at 18:04
120

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.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
pauljwilliams
  • 19,079
  • 3
  • 51
  • 79
  • Without the explicitly annotated type in the declarator, the cast is usually more common misleading by easily confusing between the intent to allocate an object (uninterested the initial value) and to allocate merely some (uninitialized) memory. – FrankHB May 13 '22 at 09:02
115

You don't cast the result of malloc, because doing so adds pointless clutter to your code.

The most common reason why people cast the result of malloc is because they are unsure about how the C language works. That's a warning sign: if you don't know how a particular language mechanism works, then don't take a guess. Look it up or ask on Stack Overflow.

Some comments:

  • A void pointer can be converted to/from any other pointer type without an explicit cast (C11 6.3.2.3 and 6.5.16.1).

  • C++ will however not allow an implicit cast between void* and another pointer type. So in C++, the cast would have been correct. But if you program in C++, you should use new and not malloc(). And you should never compile C code using a C++ compiler.

    If you need to support both C and C++ with the same source code, use compiler switches to mark the differences. Do not attempt to sate both language standards with the same code, because they are not compatible.

  • If a C compiler cannot find a function because you forgot to include the header, you will get a compiler/linker error about that. So if you forgot to include <stdlib.h> that's no biggie, you won't be able to build your program.

  • On ancient compilers that follow a version of the standard which is more than 25 years old, forgetting to include <stdlib.h> would result in dangerous behavior. Because in that ancient standard, functions without a visible prototype implicitly converted the return type to int. Casting the result from malloc explicitly would then hide away this bug.

    But that is really a non-issue. You aren't using a 25 years old computer, so why would you use a 25 years old compiler?

Vishnu CS
  • 748
  • 1
  • 10
  • 24
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 14
    "pointless clutter" is dismissive hyperbole that tends to derail any possibility of convincing anyone who doesn't already agree with you. A cast certainly isn't pointless; Ron Burk's and Kaz's answers make arguments in favor of casting that I very much agree with. Whether those concerns weigh more than the concerns you mention is a reasonable question to ask. To me, your concerns look relatively minor compared to theirs. – Don Hatch Nov 02 '16 at 08:43
  • 1
    "A void pointer can be converted to/from any other pointer type without an explicit cast" is not supported by 6.3.2.3. Perhaps you are thinking of "pointer to any object type"? "void pointer" and "pointer to a function" are not so readily convertible. – chux - Reinstate Monica Jul 27 '17 at 21:07
  • Indeed the reference was incomplete. The relevant part for the "implicitness" is the rule of simple assignment 6.5.16.1. "one operand is a pointer to an object type, and the other is a pointer to a qualified or unqualified version of void". I've added this reference to the answer for completeness. – Lundin Apr 12 '18 at 08:55
  • As I've commented to [another answer](https://stackoverflow.com/a/605858), the reason is to prevent some confusion by abusing the C language rules. Also you cannot resolve the confusion without the complete rules of object creation of C (including how _effective type_ works), so the reasoning is quite incomplete. OTOH, the similar effects in the source code can be achieved in C++ by a class type with member `template operator T*() const {...}` to replace `void*` here, but C++ still incurs no such confusion due to the stricter rules. The answer is also incomplete in this sense. – FrankHB May 13 '22 at 08:15
  • @FrankHB What do you mean? The effective type isn't affected by the cast. The returned object does not get an effective type until you write to it ("lvalue access"). – Lundin May 13 '22 at 08:22
  • There is no effective type in C until C99. This is the C's analog of C++'s *dynamic type*. In C++ dynamic types imply the well-typed nature of accessible lvalues at runtime, and it is quite close to the type of objects in languages using latent typing: both are relied on the existence of "living" objects. In C++, the nature also derives the strict aliasing rules by default, and only a few exceptional cases (copied from traditional C) should be noted. – FrankHB May 17 '22 at 21:02
  • OTOH, for compatibility issues, C's effect type has essentially looser constraints; it does not implies the existence of an object; in contrast, sometimes it is used to *determine* the creation of an object in the allocated storage. In other words, the concept is more "polymophic" than it needed to be: it can either be the type of an object, or the type of some underlying storage of some object. This is annoying because mostly it is not the programmers' intent. The special implicit conversion rule contributes to confusions in a similar way. (It is not exactly though; `void*` is from C89.) – FrankHB May 17 '22 at 21:04
  • Update: I strongly recommend to include [WG14 N2577](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2577.pdf) for everyone who really want to "know how a particular language mechanism works", which highlights the subtle problems and reflects some current consensus on a detailed semantics resolving the "ontological" meaning of some debatable operations under the hood; even though it is not just for this specific topic. – FrankHB May 30 '22 at 10:02
107

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

chqrlie
  • 131,814
  • 10
  • 121
  • 189
EFraim
  • 12,811
  • 4
  • 46
  • 62
79

Casting the value returned by malloc() is not necessary now, but I'd like to add one point that seems no one has pointed out:

In the ancient days, that is, before ANSI C provides the void * as the generic type of pointers, char * is the type for such usage. In that case, the cast can shut down the compiler warnings.

Reference: C FAQ

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • 4
    Shutting up compiler warnings is a bad idea. – Albert van der Horst Apr 01 '16 at 17:33
  • 12
    @AlbertvanderHorst Not if you're doing so by solving the exact problem the warning is there to warn you of. – Dan Bechard Apr 11 '16 at 17:17
  • 1
    @Dan . If by solving the exact problem is meant a rewrite of a subroutine to return modern ANSI C types instead of char *, I agree. I wouldn't call that shutting up the compiler. Do not give in to managers who insists that there are no compiler warnings , instead of using them by each recompilation to find possible problems. Groetjes Albert – Albert van der Horst Nov 02 '16 at 16:51
62

Just adding my experience, studying computer engineering I see that the two or three professors that I have seen writing in C always cast malloc, however the one I asked (with an immense CV and understanding of C) told me that it is absolutely unnecessary but only used to be absolutely specific, and to get the students into the mentality of being absolutely specific. Essentially casting will not change anything in how it works, it does exactly what it says, allocates memory, and casting does not effect it, you get the same memory, and even if you cast it to something else by mistake (and somehow evade compiler errors) C will access it the same way.

Edit: Casting has a certain point. When you use array notation, the code generated has to know how many memory places it has to advance to reach the beginning of the next element, this is achieved through casting. This way you know that for a double you go 8 bytes ahead while for an int you go 4, and so on. Thus it has no effect if you use pointer notation, in array notation it becomes necessary.

user3079666
  • 1,159
  • 10
  • 23
  • 4
    Except as already mentioned, the cast might hide bugs and make the code harder to analyse for the compiler or static analyser. – Lundin May 27 '14 at 07:56
  • 3
    "Essentially casting will not change anything in how it works". Casting to the matching type should not change anything, but should the var's type change and the cast no longer match, could problems come up? IWOs, the cast and var type should be kept in sync - twice the maintenance work. – chux - Reinstate Monica Aug 23 '14 at 19:29
  • 3
    I can see why Profs prefer casting. Casting may be useful from an educational standpoint where it conveys to the instructor information and the student code does not need to be maintained - its throw-away code. Yet from a coding, peer-review and **maintenance** perspective, `p = malloc(sizeof *p * n);` is so simple and better. – chux - Reinstate Monica Jul 27 '17 at 21:38
60

It is not mandatory to cast the results of malloc, since it returns void* , and a void* can be pointed to any datatype.

WedaPashi
  • 3,561
  • 26
  • 42
user968000
  • 1,765
  • 3
  • 22
  • 31
  • 3
    It's not the fact that `void*` can point to anything that enables this; it's the fact that a `void*` can be _implicitly converted_ to any other pointer type. To clarify the distinction, in C++ a `void*` can still point to anything, but implicit conversion was removed, so one must cast. – underscore_d Jul 01 '20 at 08:38
44

This is what The GNU C Library Reference manual says:

You can store the result of malloc into any pointer variable without a cast, because ISO C automatically converts the type void * to another type of pointer when necessary. But the cast is necessary in contexts other than assignment operators or if you might want your code to run in traditional C.

And indeed the ISO C11 standard (p347) says so:

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)

Slothworks
  • 1,083
  • 14
  • 18
40

A void pointer is a generic object pointer and C supports implicit conversion from a void pointer type to other types, so there is no need of explicitly typecasting it.

However, if you want the same code work perfectly compatible on a C++ platform, which does not support implicit conversion, you need to do the typecasting, so it all depends on usability.

Endeavour
  • 555
  • 4
  • 6
  • 3
    It's not a normal use case to compile a single source as both C and C++ (as opposed, say, to using a header file containing declarations to link C and C++ code together). Using `malloc` and friends in C++ is a good warning sign that it deserves special attention (or re-writing in C). – Toby Speight Aug 20 '15 at 12:57
34

The returned type is void*, which can be cast to the desired type of data pointer in order to be dereferenceable.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
swaps
  • 600
  • 5
  • 4
  • 3
    `void*` _can_ be cast to the desired type, but there is no need to do so as it will be automatically converted. So the cast is not necessary, and in fact undesirable for the reasons mentioned in the high-scoring answers. – Toby Speight Aug 20 '15 at 12:59
  • 1
    but only if you need to dereference it "on the fly", if you create a variable instead it will be converted safely and automatically into the variable's effective type, without casting (in C). – Ferrarezi Jan 08 '20 at 15:04
34

It depends on the programming language and compiler. If you use malloc in C, there is no need to type cast it, as it will automatically type cast. However, if you are using C++, then you should type cast because malloc will return a void* type.

NAND
  • 663
  • 8
  • 22
Jeyamaran
  • 783
  • 1
  • 9
  • 16
32

In the C language, a void pointer can be assigned to any pointer, which is why you should not use a type cast. If you want "type safe" allocation, I can recommend the following macro functions, which I always use in my C projects:

#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof *(ptr))
#define NEW(ptr) NEW_ARRAY((ptr), 1)

With these in place you can simply say

NEW_ARRAY(sieve, length);

For non-dynamic arrays, the third must-have function macro is

#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])

which makes array loops safer and more convenient:

int i, a[100];

for (i = 0; i < LEN(a); i++) {
   ...
}
August Karlstrom
  • 10,773
  • 7
  • 38
  • 60
  • 2
    "a void pointer can be assigned to any _object_ pointer" Function pointers are another issue, albeit not a `malloc()` one. – chux - Reinstate Monica Jul 27 '17 at 21:39
  • 1
    Assigning a `void*` to/from a function pointer may lose information so "a void pointer can be assigned to any pointer," is a problem in those cases. Assigning a `void*`, from `malloc()` to any _object_ pointer is not an issue though. – chux - Reinstate Monica Dec 26 '17 at 19:09
27

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.

  • 2
    This is pretty much the same thing as said in this old answer though: https://stackoverflow.com/a/22538350/584518. – Lundin Jun 18 '20 at 14:03
  • 1
    @Lundin You must have pasted the wrong link, this answer is completely unrelated to this one afaics – Ctx Jun 18 '20 at 14:15
  • @Lundin While I usually like content of yours very much, I need to fully disagree with you at this point here. There is a big difference between your answer and mine. Your answer clearly suggest to omit the cast in a very opinion-based way. In fact, your and unwind's answers were one of the main reasons, why I did this answer here. - You speak about "*You don't cast the result of malloc, because doing so adds pointless clutter to your code.*" and "*The most common reason why people cast the result of malloc is because they are unsure about how the C language works.*" which are not correct. – RobertS supports Monica Cellio Jun 18 '20 at 14:24
  • "*Clutter*" is a construct of one's own opinion. I completely disagree with the usage of that term in any way related to any question here on SO. That being said, I point back to [Don Hatch's comment](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/62351067#comment68003647_22538350) to your answer. – RobertS supports Monica Cellio Jun 18 '20 at 14:33
  • The latter quote suggest that only users who aren't familiar with C or don't know what they are actually doing use casting. That is totally in conflict with my answer. – RobertS supports Monica Cellio Jun 18 '20 at 14:37
  • 1
    @RobertSsupportsMonicaCellio What would you call the cast in this expression: `int x, y; x = (int)y;` then? A matter of subjective coding style? – Lundin Jun 18 '20 at 14:49
  • @Lundin This example has already been object by unwind in the comments to his question. My answer to that is equal to [Amin Negm-Awad's comment](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/62351067?noredirect=1#comment70264633_605858). – RobertS supports Monica Cellio Jun 18 '20 at 14:55
  • @Lundin I admit that the second quote is technically correct, but in the context it suggests a different meaning. IMHO It needs to be said explicitly that there is nothing wrong about casting *as is*, even it's something unsure beginners do often. As it now is, it gives the impression to me that it would actually be a *mistake* beginners do. - The difference is subtle but important to avoid your statements being ambiguous. – RobertS supports Monica Cellio Jun 18 '20 at 17:40
  • 4
    This is a bad answer because it relies on the implicit claim that all arguments in this debate are of equal value, whereas this is obviously not the case. The arguments *in favour* of the cast — with one niche exception (adherence to external code style requirements) — are simply bad arguments, for various reasons (from subjective to factually wrong). It’s fallacious to conclude that, just because sides have nominal “arguments”, the decision is therefore a toss-up, or opinion-based. In the same vein you’d both-side the non-scientific debates about biological evolution or global warming. – Konrad Rudolph Jul 29 '20 at 15:48
  • 4
    @KonradRudolph I don't see how opinion-based arguments in favor of the omission of the cast would have more value than arguments about that it is being allowed and can be used and I also do not understand why *all* of the given arguments for casting are "*bad*" arguments. The classification as "*bad*" is also subjective and opinion-based and what I wanted to prevent with this answer with just plain facts. – RobertS supports Monica Cellio Aug 03 '20 at 15:40
  • 1
    I agree very much with this answer, except for "C and C++ are in fact two completely different languages with different semantics" which is another favorite argument used to disrespect C/C++ tagged questions with something entirely unrelated, exactly like this "don't cast malloc". C++ has been *intentionally designed* so that correct C (89) programs are usually correct C++ programs **with exactly the same semanics!** The languages are emphatically not completely different and typically have exactly the same semantics (with some unfortunate and lamented deviations, e.g. concerning `volatile`). – Peter - Reinstate Monica Apr 17 '21 at 13:59
  • There do exist some wrong answers, though not necessarily to the original question. Notably, since the cast in this context is required in C++ (mentioned frequently here), the question also implies the request to answer the reason behind the differences. (And this time it would not be opinion-based.) Sadly I don't see any analysis about this topic. (No answer mentions the normative rules in C++; even very few answers mention distinguish allocation function calls from object allocations.) – FrankHB May 13 '22 at 08:34
25

People used to GCC and Clang are spoiled. It's not all that good out there.

I have been pretty horrified over the years by the staggeringly aged compilers I've been required to use. Often companies and managers adopt an ultra-conservative approach to changing compilers and will not even test if a new compiler ( with better standards compliance and code optimization ) will work in their system. The practical reality for working developers is that when you're coding you need to cover your bases and, unfortunately, casting mallocs is a good habit if you cannot control what compiler may be applied to your code.

I would also suggest that many organizations apply a coding standard of their own and that that should be the method people follow if it is defined. In the absence of explicit guidance I tend to go for most likely to compile everywhere, rather than slavish adherence to a standard.

The argument that it's not necessary under current standards is quite valid. But that argument omits the practicalities of the real world. We do not code in a world ruled exclusively by the standard of the day, but by the practicalities of what I like to call "local management's reality field". And that's bent and twisted more than space time ever was. :-)

YMMV.

I tend to think of casting malloc as a defensive operation. Not pretty, not perfect, but generally safe. ( Honestly, if you've not included stdlib.h then you've way more problems than casting malloc ! ).

20

No, you don't cast the result of malloc().

In general, you don't cast to or from void *.

A typical reason given for not doing so is that failure to #include <stdlib.h> could go unnoticed. This isn't an issue anymore for a long time now as C99 made implicit function declarations illegal, so if your compiler conforms to at least C99, you will get a diagnostic message.

But there's a much stronger reason not to introduce unnecessary pointer casts:

In C, a pointer cast is almost always an error. This is because of the following rule (§6.5 p7 in N1570, the latest draft for C11):

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
— a type compatible with the effective type of the object,
— a qualified version of a type compatible with the effective type of the object,
— a type that is the signed or unsigned type corresponding to the effective type of the object,
— a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
— an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
— a character type.

This is also known as the strict aliasing rule. So the following code is undefined behavior:

long x = 5;
double *p = (double *)&x;
double y = *p;

And, sometimes surprisingly, the following is as well:

struct foo { int x; };
struct bar { int x; int y; };
struct bar b = { 1, 2};
struct foo *p = (struct foo *)&b;
int z = p->x;

Sometimes, you do need to cast pointers, but given the strict aliasing rule, you have to be very careful with it. So, any occurrence of a pointer cast in your code is a place you have to double-check for its validity. Therefore, you never write an unnecessary pointer cast.

tl;dr

In a nutshell: Because in C, any occurrence of a pointer cast should raise a red flag for code requiring special attention, you should never write unnecessary pointer casts.


Side notes:

  • There are cases where you actually need a cast to void *, e.g. if you want to print a pointer:

    int x = 5;
    printf("%p\n", (void *)&x);
    

    The cast is necessary here, because printf() is a variadic function, so implicit conversions don't work.

  • In C++, the situation is different. Casting pointer types is somewhat common (and correct) when dealing with objects of derived classes. Therefore, it makes sense that in C++, the conversion to and from void * is not implicit. C++ has a whole set of different flavors of casting.

  • 1
    In your examples you avoid void *. there is a difference between cast from double * to int * and vice versa. malloc returns pointel aligned to the largest standard type so there are no aliasing rules broken even if someone casts form this aligned pointer to other type. – 0___________ Aug 22 '17 at 16:38
  • Aliasing has **nothing** at all to do with alignment and for the rest of your comment -- you obviously didn't get the point. –  Aug 22 '17 at 16:43
  • @PeterJ: just in case, the point is to *avoid* an unnecessary pointer cast, so it doesn't *look like* a piece of code you have to pay special attention to. –  Aug 22 '17 at 16:48
  • The strict aliasing issue doesn't really have anything to do with void pointers. In order to get bugs caused by strict aliasing violations, you must de-reference the pointed-at data. And since you can't de-reference a void pointer, such bugs are per definition not related to the void pointer but to something else. – Lundin Aug 23 '17 at 06:33
  • Rather, you would have to make a rule to ban all pointer casts. But then how would you write things like serialization routines and hardware-related programming? Things that are C's strength. Such casts are fine if you know what you are doing. – Lundin Aug 23 '17 at 06:36
  • @Lundin that's exactly the point. You sometimes **need** these casts, but you know you have to be extra careful with them, therefore you don't write *unnecessary* pointer casts. –  Aug 23 '17 at 07:10
19

I put in the cast simply to show disapproval of the ugly hole in the type system, which allows code such as the following snippet to compile without diagnostics, even though no casts are used to bring about the bad conversion:

double d;
void *p = &d;
int *q = p;

I wish that didn't exist (and it doesn't in C++) and so I cast. It represents my taste, and my programming politics. I'm not only casting a pointer, but effectively, casting a ballot, and casting out demons of stupidity. If I can't actually cast out stupidity, then at least let me express the wish to do so with a gesture of protest.

In fact, a good practice is to wrap malloc (and friends) with functions that return unsigned char *, and basically never to use void * in your code. If you need a generic pointer-to-any-object, use a char * or unsigned char *, and have casts in both directions. The one relaxation that can be indulged, perhaps, is using functions like memset and memcpy without casts.

On the topic of casting and C++ compatibility, if you write your code so that it compiles as both C and C++ (in which case you have to cast the return value of malloc when assigning it to something other than void *), you can do a very helpful thing for yourself: you can use macros for casting which translate to C++ style casts when compiling as C++, but reduce to a C cast when compiling as C:

/* In a header somewhere */
#ifdef __cplusplus
#define strip_qual(TYPE, EXPR) (const_cast<TYPE>(EXPR))
#define convert(TYPE, EXPR) (static_cast<TYPE>(EXPR))
#define coerce(TYPE, EXPR) (reinterpret_cast<TYPE>(EXPR))
#else
#define strip_qual(TYPE, EXPR) ((TYPE) (EXPR))
#define convert(TYPE, EXPR) ((TYPE) (EXPR))
#define coerce(TYPE, EXPR) ((TYPE) (EXPR))
#endif

If you adhere to these macros, then a simple grep search of your code base for these identifiers will show you where all your casts are, so you can review whether any of them are incorrect.

Then, going forward, if you regularly compile the code with C++, it will enforce the use of an appropriate cast. For instance, if you use strip_qual just to remove a const or volatile, but the program changes in such a way that a type conversion is now involved, you will get a diagnostic, and you will have to use a combination of casts to get the desired conversion.

To help you adhere to these macros, the the GNU C++ (not C!) compiler has a beautiful feature: an optional diagnostic which is produced for all occurrences of C style casts.

     -Wold-style-cast (C++ and Objective-C++ only)
         Warn if an old-style (C-style) cast to a non-void type is used
         within a C++ program.  The new-style casts (dynamic_cast,
         static_cast, reinterpret_cast, and const_cast) are less vulnerable
         to unintended effects and much easier to search for.

If your C code compiles as C++, you can use this -Wold-style-cast option to find out all occurrences of the (type) casting syntax that may creep into the code, and follow up on these diagnostics by replacing it with an appropriate choice from among the above macros (or a combination, if necessary).

This treatment of conversions is the single largest standalone technical justification for working in a "Clean C": the combined C and C++ dialect, which in turn technically justifies casting the return value of malloc.

Kaz
  • 55,781
  • 9
  • 100
  • 149
  • As other pointed out, I would usually recommend to not mix C and C++ code. However, if you have good reason to do it, then macros might be useful. – Phil1970 Jun 10 '16 at 15:53
  • @Phil1970 It's all written in one cohesive dialect, which happens to be portable to C and C++ compilers, and takes advantage of some capabilities of C++. It must be all compiled as C++, or else all compiled as C. – Kaz Jun 10 '16 at 16:45
  • I.e. what I was trying to say in the previous comment is that there is no mixing of C and C++. The intent is that the code is all compiled as C or all compiled as C++. – Kaz Jun 14 '16 at 17:35
17

The best thing to do when programming in C whenever it is possible:

  1. Make your program compile through a C compiler with all warnings turned on -Wall and fix all errors and warnings
  2. Make sure there are no variables declared as auto
  3. Then compile it using a C++ compiler with -Wall and -std=c++11. Fix all errors and warnings.
  4. Now compile using the C compiler again. Your program should now compile without any warning and contain fewer bugs.

This procedure lets you take advantage of C++ strict type checking, thus reducing the number of bugs. In particular, this procedure forces you to include stdlib.hor you will get

malloc was not declared within this scope

and also forces you to cast the result of malloc or you will get

invalid conversion from void* to T*

or what ever your target type is.

The only benefits from writing in C instead of C++ I can find are

  1. C has a well specified ABI
  2. C++ may generate more code [exceptions, RTTI, templates, runtime polymorphism]

Notice that the second cons should in the ideal case disappear when using the subset common to C together with the static polymorphic feature.

For those that finds C++ strict rules inconvenient, we can use the C++11 feature with inferred type

auto memblock=static_cast<T*>(malloc(n*sizeof(T))); //Mult may overflow...
user877329
  • 6,717
  • 8
  • 46
  • 88
  • 22
    Use a C compiler for C code. Use a C++ compiler for C++ code. No ifs, no buts. Rewriting your C code in C++ is another thing entirely, and may - or may not be - worth the time and the risks. – Toby Speight Jun 25 '15 at 21:06
  • 4
    I'd like to add to @TobySpeight advice: If you need to use C code in a C++ project, you can usually compile the C code as C (e.g. `gcc -c c_code.c`), the C++ code as C++ (e.g. `g++ -c cpp_code.cpp`), **and then link them together** (e.g. `gcc c_code.o cpp_code.o` or vice-versa depending upon the project dependencies). Now there should be no reason to deprive yourself of any nice features of either language... – autistic Dec 07 '15 at 16:06
  • 1
    @user877329 It's a more sensible alternative to painstakingly adding casts to code that reduce the code's legibility, only for the sake of being "C++ compatible". – autistic Dec 08 '15 at 00:54
  • 1
    Other advantages to C over C++: C99 variable-length arrays for very efficient allocation/deallocation of scratch space. You can't accidentally write non-constant initializers when you didn't mean to (e.g. if you thought you were being clever by putting `static const __m128 ones = _mm_set1_ps(1.0f);` at the global scope so multiple functions could share a constant, the fact that constructors aren't a thing in C stops you from generating worse code. (This is really finding a silver lining to a C limitation...)) – Peter Cordes Oct 24 '16 at 15:11
  • 1
    Probably the main advantage in this context is that C lets you write `p = malloc(sizeof(*p));`, which doesn't need changing in the first place if `p` changes to a different type name. The proposed "advantage" of casting is that you get a compile error if `p` is the wrong type, but it's even better if it Just Works. – Peter Cordes Oct 24 '16 at 15:13
  • 1
    I would like to mention that writing in C may be necessary when targeting platforms lacking proper C++ compilers. Exceptions and templates are features that typically help c++ to generate smaller and / or more efficient code while runtime polymorphism in C++ is mostly equivalent to C. – user7860670 Jan 15 '20 at 09:05
17

I prefer to do the cast, but not manually. My favorite is using g_new and g_new0 macros from glib. If glib is not used, I would add similar macros. Those macros reduce code duplication without compromising type safety. If you get the type wrong, you would get an implicit cast between non-void pointers, which would cause a warning (error in C++). If you forget to include the header that defines g_new and g_new0, you would get an error. g_new and g_new0 both take the same arguments, unlike malloc that takes fewer arguments than calloc. Just add 0 to get zero-initialized memory. The code can be compiled with a C++ compiler without changes.

Nae
  • 14,209
  • 7
  • 52
  • 79
proski
  • 3,603
  • 27
  • 27
15

Casting is only for C++ not C.In case you are using a C++ compiler you better change it to C compiler.

13

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++.

Aashish Kumar
  • 2,771
  • 3
  • 28
  • 43
10

The concept behind void pointer is that it can be casted to any data type that is why malloc returns void. Also you must be aware of automatic typecasting. So it is not mandatory to cast the pointer though you must do it. It helps in keeping the code clean and helps debugging

iec2011007
  • 1,828
  • 3
  • 24
  • 38
  • 14
    "_It is not mandatory -- though you must do it_" - I think there's a contradiction there! – Toby Speight Aug 20 '15 at 12:54
  • 9
    I think you should read this post to someone, and see if they understand what you are trying to say. Then rewrite it, making it clear what you want to say. I really can't understand what your answer is. – Bill Woodger Sep 08 '15 at 12:28
10

A void pointer is a generic pointer and C supports implicit conversion from a void pointer type to other types, so there is no need of explicitly typecasting it.

However, if you want the same code work perfectly compatible on a C++ platform, which does not support implicit conversion, you need to do the typecasting, so it all depends on usability.

10
  1. As other stated, it is not needed for C, but for C++.

  2. Including the cast may allow a C program or function to compile as C++.

  3. In C it is unnecessary, as void * is automatically and safely promoted to any other pointer type.

  4. But if you cast then, 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).

    Because stdlib.h contains the prototype for malloc is found. In the absence of a prototype for malloc, the standard requires that the C compiler assumes malloc returns an int. If there is no cast, a warning is issued when this integer is assigned to the pointer; however, with the cast, this warning is not produced, hiding a bug.

Mohit
  • 885
  • 9
  • 7
4

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.

tstanisl
  • 13,520
  • 2
  • 25
  • 40
1

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.

pasignature
  • 577
  • 1
  • 6
  • 13