Winston <w...@ubeblock.psr.com.invalid> wrote
in <
ydr1lsa...@UBEblock.psr.com>:
# Passing char *p to a function foo(const char *p) is common.
#
# Passing const char *p to a function foo(char *p) gets a warning about
# discarding const, as one would expect.
#
# Maybe I'm just not thinking clearly at the moment, but I don't see why
# passing char *p using foo(&p) to the function foo(const char **pp) causes
# this warning:
#
# [...].c: warning: passing 'char **' to parameter of type 'const char **'
# discards qualifiers in nested pointer types
# [-Wincompatible-pointer-types-discards-qualifiers]
#
# [...].h: note: passing argument to parameter 'pp' here
# extern char * foo(const char **pp);
#
# Is this a bug, or what am I missing?
This looks like a C FAQ:
http://c-faq.com/ansi/constmismatch.html
comp.lang.c FAQ list · Question 11.10
Q: 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:
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, if you must assign or pass pointers which have qualifier
mismatches at other than the first level of indirection, you must use
explicit casts (e.g. (const char **) in this case), although as always,
the need for such a cast may indicate a deeper problem which the cast
doesn't really fix.
References: ISO Sec. 6.1.2.6, Sec. 6.3.16.1, Sec. 6.5.3
H&S Sec. 7.9.1 pp. 221-2
Regards,
Jens
--
Jens Schweikhardt
http://www.schweikhardt.net/
SIGSIG -- signature too long (core dumped)