Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C++ require a cast for malloc() but C doesn't?

Tags:

c++

c

malloc

I have always been curious about this - why do in C++ I have to cast return value from malloc but not in C?

Here is the example in C++ that works:

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

And here is the example in C++ that doesn't work (no cast):

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

I heard that in C, in fact, casting an output from malloc() is a mistake.

Can anyone comment on this topic?

like image 717
bodacydo Avatar asked Aug 13 '10 14:08

bodacydo


People also ask

Why do we need to cast malloc in C?

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.

Why do we need to typecast while calling malloc () and calloc ()?

Is it necessary to type-cast malloc and calloc. And why ? No, because the conversion from a pointer to void to a pointer to object is implicit. A pointer to void may be converted to or from a pointer to any object type.

Why is malloc not working in C?

So the first case of malloc() failing is when a memory request can not be satisfied because (1) there is not a usable block of memory on the list or heap of the C runtime and (2) when the C runtime memory management requested more memory from the operating system, the request was refused.

Do you have to cast malloc in C++?

C++ does not. Casting the result of malloc() in C will supress a useful diagnostic if you forget to include stdlib. h or otherwise don't have a declaration for malloc() in scope. Remember that if C sees a function call without a prior declaration, it will assume that the function returns int .


4 Answers

Several points:

C allows void pointers to be implicitly converted to any other object pointer type. C++ does not.

Casting the result of malloc() in C will supress a useful diagnostic if you forget to include stdlib.h or otherwise don't have a declaration for malloc() in scope. Remember that if C sees a function call without a prior declaration, it will assume that the function returns int. If you don't have a declaration for malloc() and you leave off the cast, you'll get a diagnostic to the effect that you're trying to assign incompatible types (int to pointer). If you cast the result, you supress the diagnostic and will potentially have runtime issues, since it's not guaranteed that converting a pointer value to an int and back to a pointer again will give you a useful result.

If you're writing C++, you should be using new and delete instead of malloc() and free(). Yeah, yeah, yeah, I've heard all the reasons why people want their code to compile as both C and C++, but the benefits of using the right memory management tool for the language outweigh the cost of maintaining two versions IMO.

Note: the void * type was added in the C89 standard; earlier versions of C had malloc() return char *, so in those versions the cast was required if you were assigning the result to a different pointer type. Almost everybody supports at least the C89 standard though, so the odds of you running into one of those older implementations is very, very low.

like image 130
John Bode Avatar answered Oct 07 '22 06:10

John Bode


That's because C++ is a strongly-typed language. In C++, implicit casts are only allowed if they are "widening", that is, if the new type can hold every value that the old type can hold. Casting from a smaller integer type to a larger integer type is allowed; casting from any pointer type to void* is allowed; casting from a subclass to its superclass is allowed. All other casts must be made explicitly, thereby telling the compiler "I know what I'm doing, this is not a mistake".

malloc() returns a void*, which could be anything, so the compiler cannot guarantee that your cast will succeed (or be meaningful). By using an explicit cast, you're telling the compiler that what you're doing is actually intentional.

C, OTOH, does not have such rigid casting rules; you can happily cast between any two types, and you as the programmer are responsible for making sure no bad things happen as a consequence.

like image 21
tdammers Avatar answered Oct 07 '22 08:10

tdammers


C supports implicit cast from void* to other pointer types. C++ disallows it.

One reason that it's frowned upon in C to explicitly cast the return value of malloc is that if the malloc signature is not included in the current compilation unit, the compiler will assume that the return type is int and implicit conversion of it to the pointer type you're assigning to results in a compile-time warning you'd immediately resolve. With an explicit cast, if you make this mistake, no warning will be issued.

like image 37
mmx Avatar answered Oct 07 '22 08:10

mmx


C has very lax type rules and C++ has somewhat stricter rules. The difference in this case is that C allows implicit conversion/assignment between object pointers and void pointers. C++ does not.

In fact old style C even encouraged implicit conversion to/from void pointers, as part of old style generic C programming. C++ never needed void pointers for such, since it got function overloading and templates etc. Using void pointers in C++ is often fishy.

Regarding beating the dead horse debate about casting the result of malloc causing bugs in case stdlib.h wasn't included, doing so has never been valid C++ and it has not been valid C either for the past 21 years.

Best practices:

C

  • If you are compiling with -std=c89, -ansi or -dinosaur etc, then don't cast.
  • Otherwise, follow your coding standard.
    • If it allows implicit conversions between void and object pointers, don't cast.
    • If it doesn't allow it, then do cast (this probably implies you are using static code analysis).
    • If you have no coding standard, then it really doesn't matter much. The cast is harmless but adds clutter.

C++

  • Always cast.
  • Avoid void pointers.
  • Most importantly, avoid malloc and use new/new[] instead.
like image 32
Lundin Avatar answered Oct 07 '22 06:10

Lundin