Re: Incompatible pointer type question
The only person I know who can make sense of this stuff
(i.e. distill the discussions on this topic in comp.std.c
down to language which mere mortals can understand) is Tanmoy
Bhattacharya. Here's the book's version of question 11.10,
much of which basically paraphrases a message Tanmoy once sent me:
11.10: Why can't I pass a char ** to a function which expects a
const char **?
A: You can use a pointer-to-T (for any type T) where a pointer-to-
const-T is expected. However, the rule (an explicit exception)
which permits slight mismatches in qualified pointer types
is not applied recursively, but only at the top level.
(const char ** is pointer-to-pointer-to-const-char, and the
exception therefore does not apply.)
The reason that you cannot assign a char ** value to a
const char ** pointer is somewhat obscure. Given that the
const qualifier exists at all, the compiler would like to help
you keep your promises not to modify const values. That's why
you can assign a char * to a const char *, but not the other
way around: it's clearly safe to "add" const-ness to a simple
pointer, but it would be dangerous to take it away. However,
suppose you performed the following more complicated series of
assignments:
Code:
const char c = 'x'; /* 1 */
char *p1; /* 2 */
const char **p2 = &p1; /* 3 */
*p2 = &c; /* 4 */
*p1 = 'X'; /* 5 */
In line 3, we assign a char ** to a const char **. (The
compiler should complain.) In line 4, we assign a const char *
to a const char *; this is clearly legal. In line 5, we modify
what a char * points to -- this is supposed to be legal.
However, p1 ends up pointing to c, which is const. This came
about in line 4, because *p2 was really p1. This was set up
in line 3, which is an assignment of a form that is disallowed,
and this is exactly *why* line 3 is disallowed.
Assigning a char ** to a const char ** (as in line 3, and in the
original question) is not immediately dangerous. But it sets up
a situation in which p2's promise -- that the ultimately-pointed-
to value won't be modified -- cannot be kept.
(C++ has more complicated rules for assigning const-qualified
pointers which let you make more kinds of assignments without
incurring warnings, but still protect against inadvertent
attempts to modify const values. C++ would still not allow
assigning a char ** to a const char **, but it would let you
get away with assigning a char ** to a const char * const *.)
In C, you must use explicit casts (e.g. (const char **) in this
case) when assigning (or passing) pointers which have qualifier
mismatches at other than the first level of indirection.
References: ANSI Sec. 3.1.2.6, Sec. 3.3.16.1, Sec. 3.5.3
ISO Sec. 6.1.2.6, Sec. 6.3.16.1, Sec. 6.5.3
H&S Sec. 7.9.1 pp. 221-2