You need to protect contents on both levels of dereference of the pointer. With const char**
you could actually modify contents on the 1st dereference.
char *tmp = "foo"; //Deprecated but it's ok for the example
void f1(const char** a)
{
a[0] = tmp; //this is legal
a[0][1] = 'x'; //this is not
}
And this is most probably not intended. It should look like this:
char *tmp = "foo"; //Deprecated but it's ok for the example
void f1(char const* const* a)
{
a[0] = tmp; // this is not legal any more
a[0][1] = 'x'; // this still upsets compiler
}
The compiler does not allow implicit conversion to such "partially" protected pointer types. Allowing such conversion could have nasty consequences as discussed in c++faq pointed out in comment by @zmb. This answer also cites how could you violate constness of an object if this was allowed, using char
examples.
One can however implicitly convert to a "fully" protected pointer as shown in the 2nd code example so below code compiles.
void f1(char const* const* a){}
void f2(const char* b){}
int main(int argc, char const *argv[])
{
char* c;
f1(&c); // works now too!
f2(c); // works
return 0;
}
Actually there is a bunch of questions and answers on this matter lying around. E.g:
- invalid conversion from ‘char**’ to ‘const char**’
- Why am I getting an error converting a ‘float**’ to ‘const float**’?
EDIT: I got the 1st example wrong by a bit. Thank for pointing it out!