Initialization between types "const int ** const" and "int **" is invalid, why?

Using the V1.8 z / OS XL C compiler, with warnings raised with INFO (ALL), I get the following warning on line 4 of the code below:

WARNING CCN3196 Initialization between types "const int** const" and "int**" 
                is not allowed.


1  int foo = 0;
2  int *ptr = &foo;

3  const int * const fixed_readonly_ptr = ptr;

4  const int ** const fixed_ptr_to_readonly_ptr = &ptr;

      

I cannot wrap my head around why I am getting this warning. If I can assign an int pointer to a const pointer to const int (line 3), then why can't I assign the address of an int pointer to a const pointer to a const int pointer? What am I missing?

Please note that the above code is a thumbnail example that just shows the problem I'm having in a little bit of code. The real context is that I have a const pointer to a pointer to a struct (struct s ** const) and pass it as a function argument whose parameter is defined as a const pointer to a pointer to a const struct (const struct s ** Const). This is because the function will not modify the data in the structure (hence the first constant) and does not change the pointer parameter, which always contains the address passed (hence the second const). The value of the pointer that the pointer points to can be changed by path (which is why there is no third constant between the ** symbol).

+2


source to share


3 answers


The C rule is that you can convert a pointer to something to a pointer to const something, but something must be exactly the same type, including a constant and volatile qualification further down the chain.

The rationale behind this rule is that if the second of these two lines is allowed:

int *ptr;

const int ** const fixed_ptr_to_readonly_ptr = &ptr;

      



then this can be used to breach non-cast type safety.

const int i = 4;

// OK, both sides have type const int *
*fixed_ptr_to_readonly_ptr = &i;

// the value of fixed_ptr_to_readonly_ptr is still &ptr
// the value of ptr is now &i;

*ptr = 5;

// oops, attempt to change the value of i which is const

      

+3


source


This is a type safety violation. Consider this code (I messed up a bit const

to figure out if it applies to a pointer or a pointer, but semantically it means the same thing):



int* p = 0;
int const** pp = &p; // presumably ok

int const c = 123;
*pp = &c; // okay, &c is int const*, and *p is int const* lvalue

*p = 666; // okay, *p is int lvalue

// wait, so we just changed the value of (const) c above, with no const_cast!

      

+5


source


This is a type safety violation. You probably want to use const int * const *. See http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17

0


source







All Articles