Passing variable to function with constant parameter

157 Views Asked by At

I'm very confused. I saw that when the code be like

void fun(const char **p) { }
int main(int argc, char **argv)
{
   fun(argv);
   getchar();
   return 0;
}

And it shows error: invalid conversion from 'char**' to 'const char**'

But when the code be like

void test(const char *p) { }
int main()
{
    char *c = new char('a');
    test(c);
}

Then there is no compile error. What is the difference between two codes?
Why can the second code pass a variable to the function with constant parameter?

1

There are 1 best solutions below

0
Passer By On BEST ANSWER

Pointers to pointers are weird. Take this example

const int i = 42;
int* p;
const int** pp = &p;  // safe?
*pp = &i;  // *pp refers to p, but has the type const int*
*p = 420;  // !!

Clearly you should not be able to defeat const just by assigning pointers around, so the conversion from T** to const T** is illegal.


But wait a minute, why is converting T* to const T* legal in the first place?

Right, it's because each T can be treated as a const T. A const T is only a restriction of T. No operation on const T will be illegal on T. If you view types as representing a set of legal operations on objects, then const T represents a subset of T.

However, restricting the pointee has the opposite effect on the pointer. A const T* is not a subset of T*. A T* can only point to non-const T while const T* can point to any T. In terms of just assignment on the pointer itself, const T* is a superset of T*, not the other way around.

So why isn't a conversion from T** to const T** legal? Because T* is not a superset of const T*: not all T* can be treated as a const T*, as demonstrated by the opening snippet.

†But if you dereference the pointer, const T is a subset of T again, so const T* and T* aren't subsets of each other.