I believe the problem is the constraints specified in C99 6.5.16.1(1), which seem to prohibit mixing qualifications in assignments, except for pointers for which an inclusive-qualifier exception is defined. The problem is that with indirect pointers, you end up passing a pointer to one thing to a pointer to another. The assignment isn’t valid because, if it was, you could fool it into modifying a const-qualified object with the following code:
const char **cpp;
char *p;
const char c="A";
cpp = &p; // constraint violation
*cpp = &c; // valid
*p = 0; // valid by itself, but would clobber c
It might seem reasonable that cpp
, which promises not to modify any char
s, might be assigned a pointer to an object pointing at non-qualified char
s. After all, that’s allowed for single-indirect pointers, which is why, e.g., you can pass a mutable object to the second parameter of strcpy(3)
, the first parameter to strchr(3)
, and many other parameters that are declared with const
.
But with the indirect pointer, at the next level, assignment from a qualified pointer is allowed, and now a perfectly unqualified pointer assignment will clobber a qualified object.
I don’t immediately see how a 2-D array could lead to this situation, but in any case it hits the same constraint in the standard.
Since in your case, you aren’t actually tricking it into clobbering a const, the right thing for your code would seem to be inserting the cast.
Update: OK guys, as it happens this issue is in the C faq, and this entire discussion has also taken place several times on the gcc bug list and on the gcc mailing list.
- Gcc bug list: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20230.
- C FAQ: it’s question 11.10: http://c-faq.com/ansi/constmismatch.html
The lesson: you can pass a T *x
when const T *x
is expected, by explicit exception, but T *x
and const T *x
are still distinct types, so you can’t pass a pointer to either one to a pointer to the other.