Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why we cannot implicitly assign from a void* to any other type in C++ but its preferred in C? [duplicate]

Tags:

c++

c

malloc

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 ?

like image 685
Vikas Verma Avatar asked Jan 23 '14 17:01

Vikas Verma


People also ask

What does type 'void is not assignable to type 'number' mean?

When you don't return a value from a function, you implicitly return undefined and the function's return type is inferred to be void. The error message "Type 'void' is not assignable to type 'number'" means that we have a value that expects an assignment of type number and we're trying to assign a value of type void to it.

Why aren't `Void *`'s implicitly cast in C++?

Why aren't `void *`'s implicitly cast in C++? In C, there is no need to cast a void * to any other pointer type, it is always safely promoted. However, in C++, this is not the case. E.g., works in C, but not in C++.

Can a pointer to a void be assigned to another void?

Section 5.6 is named Pointers to Void and there Stroustrup writes: A pointer to any type of object can be assigned to a variable of type void*, a void* can be assigned to another void*, void* can be compared for equality and inequality, and a void* can be explicitly converted to another type.

Why doesn't C++ allow type errors?

That's because C assumes that the programmer knows exactly what they are doing, and if not, it is the programmer's problem, not the compiler's problem. C++ will usually disallow things that could potentially be errors, and require you to explicitly state your intention with a type cast.


2 Answers

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.

like image 169
Stephen Canon Avatar answered Oct 02 '22 22:10

Stephen Canon


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.

like image 24
Mike Seymour Avatar answered Oct 02 '22 21:10

Mike Seymour