6

According to this

It is preferred to not cast malloc in C because if the return of malloc is cast then the error which would be flagged is hidden, resulting in a difficult to find bug. Also, during maintenance, if the type of the pointer changes but the cast is not changed, once again there is a difficult to find bug. The method most experienced programmers choose is:

p = malloc ( n * sizeof *p );

There is no cast for malloc since there is no need for one, and instead of using sizeof ( type ) to determine the size of the block, sizeof *ptr is used. By dereferencing the pointer and taking its size, the proper value is given without having to worry about modifying the allocation request if the type of the pointer changes.

but it won't compile in C++. why?

and what does it means that if the return of malloc is cast then the error which would be flagged is hidden ?

Vikas Verma
  • 3,626
  • 6
  • 27
  • 40
  • 7
    Why are you using malloc() in C++, and not the new() operator? – OldProgrammer Jan 23 '14 at 17:55
  • 1
    In C++ you have the `new` operator that does a clean, typed allocation. Using `malloc` in C++ is really asking for trouble, since it will call the exact same code as `new` to perform the allocation but will bring back the `void *` cast and object size computation problems that `new` can easily avoid. – kuroi neko Jan 23 '14 at 17:56
  • @OldProgrammer yeah I can use new() but I just want to know why its not preferred in C++ if its preferred in C ? – Vikas Verma Jan 23 '14 at 18:04

4 Answers4

8

it won’t compile in C++. why?

Because C and C++ are different languages.

Implicit conversions between void * and other pointer types are allowed by the C standard. They are not allowed by the C++ standard. In C the cast is unnecessary, and fails the basic programming guideline of “don’t repeat yourself”, whereas in C++ the language requires a cast (it’s not a question of preference).

what does it means that if the return of malloc is cast then the error which would be flagged is hidden ?

Implicit function declaration is no longer part of the C language, but many compilers continue to support it as an extension for compatibility with old codebases. If a C function does not have a prototype, it is assumed to return int. If you inadvertently leave #include <stdlib.h> out of your code but call malloc, the compiler may assume that it returns int instead of void *[1]. With an explicit cast, the assumed int result will be converted to a void * which in general may result in an invalid pointer. This is bad, and may result in hard-to-diagnose runtime failures.

If, on the other hand, you do not have an explicit cast, you will get a warning or error at compile time pointing to the exact source of the error, which is much easier to diagnose and fix.[2]


  1. In practice, this is less of an issue with malloc than it is with your own functions that return pointers (or other types), as many compilers know about malloc and handle it specially.

  2. In practice, some modern compilers will actually warn whether or not you have the cast, but there are definitely compilers still in use that will not warn if the cast is present, which leads to justified paranoia and defensive programming.

Stephen Canon
  • 103,815
  • 19
  • 183
  • 269
  • 2
    Very true but can you really say this is adding to the discussion ? – cnicutar Jan 23 '14 at 17:56
  • @cnicutar: No further rationalisation is either useful or warranted. This is the _end_ of the discussion! – Lightness Races in Orbit Jan 23 '14 at 17:57
  • 2
    @cnicutar: It’s the only factually correct answer to the [first] question being asked. I’ll expand it to address the second question as well. – Stephen Canon Jan 23 '14 at 17:57
  • 1
    Eh.. I won't downvote but while correct and complete I see it as slightly snarky and not teaching the community much. – cnicutar Jan 23 '14 at 17:58
  • @StephenCanon but C++ is based on C so, if its preferred not need to cast malloc in C so why not preferred in C++ my question is that. – Vikas Verma Jan 23 '14 at 18:01
  • @VikasVerma: C and C++ are different languages. C++ was originally based on some dialect of 1980-era C, but both languages have evolved independently since then. This is one of many aspects that differ between them. – Mike Seymour Jan 23 '14 at 18:20
  • Building on what @MikeSeymour said, this was a common type of bug in code around the time period that C++ was created. C++ addressed the problem in one way (stricter rules about implicit conversions) whereas C addressed it in another way (elimination of implicit function declaration, and more exhaustive warnings in compilers). The two languages have made many other divergent decisions in the past 30 years, and the modern styles of both languages are quite different. – Stephen Canon Jan 23 '14 at 18:22
  • 3
    I think it is more directly to the point that (a) C must allow conversions to and from `void *` because C does not have features that support avoiding it, (b) C++ does not allow conversions to and from `void *` because it is dangerous and C++ does have features that support avoiding it, and (c) inserting casts in C may mask errors where a compiler would warn if an `int` or `float *` were implicitly converted to an `int *` but does not warn if an explicit cast is used. – Eric Postpischil Jan 23 '14 at 18:29
  • @EricPostpischil: Agreed (though “C” doesn’t warn or not warn except in a few cases, and some modern compilers do flag conversions from `int` to `int *`, even with an explicit cast). – Stephen Canon Jan 23 '14 at 18:31
8

but it won't compile in C++. why?

It's a trade-off between the convenience of using void* as a generic pointer, and the safety of preventing invalid type conversions.

In C, void* is widely used, as it's the only reasonable way to write generic code; so, in that language, it can be implicitly converted to another pointer type for convenience.

In C++, there are type-safe ways of writing generic code, so void* is rarely used; in particular, you'd use the type-safe new to allocate and initialise an object, rather than malloc to allocate raw memory and pretend it contained an object. So, in that language, implicit conversion from void* is forbidden to give stronger type safety.

and what does it means that if the return of malloc is cast then the error which would be flagged is hidden ?

The clue is in the previous sentence:

There is nothing wrong with this except in the event that stdlib.h, the header which declares malloc, is not included

In (older dialects of) C, you can call a function which hasn't been declared; that implicitly declares a function with a return type of int. So, if you were to call malloc without including the header, you'd get code that erroneously assumed that it returned int. Without a cast, you'd get a compiler error when you tried to assign it to a pointer. With a cast, the code would compile, potentially giving obscure runtime errors and lengthy debugging sessions.

In C++ (and modern C), all functions must be declared before use, so this error couldn't happen even if you did use malloc for some reason.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Formally, you cannot call a function which hasn’t been declared "in C"; implicit function declarations were removed from standard C long ago. Obviously, some compilers continue to support this as an extension, but it is not part of the language. – Stephen Canon Jan 23 '14 at 18:14
  • @StephenCanon: Fair enough; I haven't used C much in the last decade, and generally stick to C90 when I do, so I'm not up-to-date on recent developments in the language. – Mike Seymour Jan 23 '14 at 18:17
1

It has to do with type safety. Specifically C allows implicit casting from void* to other types but c++ doesn't, this is why it compiles in C but not C++. This is one of the ways in which C and C++ are different. C is not a subset of C++.

In c++ you should be using new and not malloc. New does a type safe allocation which gets around this issue.

shuttle87
  • 15,466
  • 11
  • 77
  • 106
1

It's not allowed in C++ language, because C++ has type safety

eerorika
  • 232,697
  • 12
  • 197
  • 326