Why is char ** (or any T **) for void ** cast invalid?
In the first comment on Python C Module - Malloc does not work in specific Python version , @ user694733 mentions that casting char**
in is void**
not allowed. I have read Invalid Conversion from Foo ** to void ** - why is implicit type conversion allowed to void * but not void **? and http://c-faq.com/ptrs/genericpp.html , but there is a reference to the standard but no real example, in which case it might not be correct, which leads to errors. Thinking about, for example, void**
before double**
or vice versa, is there a case where it might go wrong? Why (technically, not just because it's UB)?
but there is a reference to the standard, but no real example, in which case it might not be correct, which leads to errors
This is not true. The page http://c-faq.com/ptrs/genericpp.html you mentioned points to another page http://c-faq.com/null/machexamp.html which contains example machines with different pointer sizes for different types:
The Eclipse MV series from Data General has three architecture-supported pointer formats (words, bytes, and bit pointers), two of which are used by C compilers: byte pointers for char * and void *, and word pointers for everything else. For historical reasons, during the evolution of the 32-bit MV line from the 16-bit Nova line, word pointers and byte pointers had offset, indirection, and ring protection bits at different places in the word. Passing an inconsistent pointer format to a function resulted in security errors. In the end, the MV C compiler added a lot of compatibility options to try and handle the code with pointer mismatch errors.
If allowed, it would create a loophole in the type system:
T* ptr;
void **vptr = &ptr; // &ptr is of type T**
int value;
*vptr = &value; // &value is int*, can be converted to void*
At this point ptr
, which, according to the type system, is a pointer T
to value
, which is int
. Although the language allows you to bypass the type system, you must explicitly request it. Implicit conversions are designed to prevent these kinds of problems.
The biggest practical problem is multiple inheritance. When you use a pointer to a class with multiple base classes, the actual value of the pointer will depend on the pointer type, and the compiler inserts a code fix to customize it when you assign from one pointer type to another. When you have a pointer to a pointer, the compiler no longer has the ability to make these corrections, so this operation is prohibited by the standard.