Hello,
I know (void **) is not "compatible" with (foo **) but I'm wondering why.
I can write void *pv = 0; int *pi = 0; pv = pi; pi = pv;
Why is a pointer to v not be compatible with a pointer to i?
There's two ways to answer that, depending upon what you mean by the
"Why". First of all, there's the applicable citations from the standard:
"For two pointer types to be compatible, both shall be identically
qualified and both shall be pointers to compatible types." (6.7.6.1p2)
Because there's two levels of indirection involved here, that rule gets
applied twice.
Since void and foo are not compatible types (I assume that foo is NOT a
typedef for void), then void* and foo* are not compatible types. If
void* and foo* are not compatible types, void** and foo** are not
compatible types.
The second way to answer that is in terms of the reason why that rule
was written that way. Consider a machine with 16 bit addresses and a
word size of 32 bits. This is just an example chosen to clarify the
reasons behind that decision; machines with precisely that combination
of characteristics (which are probably a bit unusual) are NOT the reason
why this rule was adopted.
C requires that char* pointers uniquely identify bytes. One option would
be to choose CHAR_BIT==32, but a more conventional approach would be to
choose CHAR_BIT==8, and to access char* using pointers that are more
than 16 bits long. 16 of those bits would identify the particular word
containing the char, and 2 additional bits would be used to identify
which particular byte within that word contains the char. On such an
implementation, 3 bytes would be the minimum size of such a pointer, but
it would probably be rounded up to 4 bytes == 32 bits. Some such scheme
must be used for any object that has a size less than the word size -
let's call that the large pointer format. However, if larger types are
always aligned on word boundaries, pointers to those types only need to
contain 16-bit addresses - let's call that the small pointer format.
Problems like this one are the main reason that the standard allows
pointers to different types to have different representations, sizes,
and alignment requirements. This particular problem only requires
pointers of two different formats, but the standard allows an
arbitrarily large number of mutually incompatible pointer formats.
However, the standard does require that a void* have the same
representation and alignment requirements as a char*, so on such a
machine, it must have the large format. On the other hand, if
sizeof(foo)>4, foo* could use the small format.
OK, now let's apply that one more time: since sizeof(void*) == 4, void**
can use the small pointer format. However, if sizeof(foo*)==2, then
foo** must use the large pointer format. Those two formats are
inherently incompatible.