Инициализация между типами «const int** const» и «int**» не допускается, почему?

StackOverflow https://stackoverflow.com/questions/1468148

Вопрос

Используя компилятор C v1.8 z/OS XL с предупреждениями, поднятыми с помощью INFO(ALL), я получаю следующее предупреждение в строке 4 приведенного ниже кода:

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;

Я не могу понять, почему я получаю это предупреждение.Если я могу назначить указатель int константному указателю на const int (строка 3), то почему я не могу присвоить адрес указателя int константному указателю на const int?Что мне не хватает?

Обратите внимание, что приведенный выше код представляет собой уменьшенный пример, просто показывающий проблему, с которой я столкнулся в небольшом объеме кода.Реальный контекст таков, что у меня есть константный указатель на указатель на структуру (struct s** const), и я передаю его в качестве аргумента функции, параметр которой определен как константный указатель на указатель на const struct (const struct s** константа).Это связано с тем, что функция не будет изменять данные в структуре (отсюда первая константа) и не изменяет параметр-указатель, который всегда содержит переданный адрес (отсюда и вторая константа).Значение указателя, на который указывает, может быть изменено (именно поэтому между ** НЕТ третьей константы).

Это было полезно?

Решение

Правило C заключается в том, что вы можете преобразовать указатель на что-то в указатель на что-то константное, но это что-то должно быть точно такого же типа, включая константные и изменчивые квалификации, расположенные дальше по цепочке.

Обоснование этого правила заключается в том, что если бы была разрешена вторая из этих двух строк:

int *ptr;

const int ** const fixed_ptr_to_readonly_ptr = &ptr;

тогда это можно использовать для нарушения безопасности типов без приведения типов.

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

Другие советы

Это нарушение типовой безопасности.Рассмотрим этот код (я перетасовал const немного, чтобы прояснить, относится ли это к указателю или указателю, но семантически это означает одно и то же):

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!

Это нарушение типовой безопасности.Вероятно, вместо этого вы захотите использовать const int * const *.Видеть http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top