Question

I'm trying to understand the differences between C and C++ with regards to void pointers. the following compiles in C but not C++ (all compilations done with gcc/g++ -ansi -pedantic -Wall):

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

Because malloc returns void*, which C++ doesn't allow to assign to int* while C does allow that.

However, here:

void foo(void* vptr)
{
}

int main()
{
    int* p = (int*) malloc(sizeof(int));
    foo(p);
    return 0;
}

Both C++ and C compile it with no complains. Why?

K&R2 say:

Any pointer to an object may be converted to type void * without loss of information. If the result is converted back to the original pointer type, the original pointer is recovered.

And this pretty sums all there is about void* conversions in C. What does C++ standard dictate?

Was it helpful?

Solution

In C, pointer conversions to and from void* were always implicit.

In C++, conversions from T* to void* are implicit, but void* to anything else requires a cast.

OTHER TIPS

C++ is more strongly-typed than C. Many conversions, specially those that imply a different interpretation of the value, require an explicit conversion. The new operator in C++ is a type-safe way to allocate memory on heap, without an explicit cast.

It is useful to understand that pointer type conversions don't really require execution of extra CPU instructions. They are analysed during the compile time to understand the intensions of the developer. void * is an opaque pointer. All it says that the type of pointed object is unknown. C is weakly typed. It allows direct conversion between (void *) and any (T*) implicitly. C++ is strongly typed. A conversion from (void *) to (T*) wouldn't really make good case for a strongly typed language. But C++ had to stay backwards compatible with C, hence it had to allow such conversions. The guiding principle then is: explicit is better than implicit. Hence if you wish to convert an (void*) to some specific (T*) pointer, you need to explicitly write that in code. Conversion from (T*) to (void*) doesn't require explicit conversion since there is nothing much one can do on a (void*) pointer directly (one can call free() though). Hence (T*) to (void*) conversion is pretty much safe.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top