Предупреждения о двойной ошибке указателя в C
Указатель на неконстантные данные может быть неявно преобразован в указатель на данные const того же типа:
int *x = NULL;
int const *y = x;
Добавление дополнительных конструкторов констант в соответствие с дополнительной косвенностью должно логически работать одинаково:
int * *x = NULL;
int *const *y = x; /* okay */
int const *const *z = y; /* warning */
Однако компиляция с помощью GCC или Clang с флагом -Wall
приводит к следующему предупреждению:
test.c:4:23: warning: initializing 'int const *const *' with an expression of type
'int *const *' discards qualifiers in nested pointer types
int const *const *z = y; /* warning */
^ ~
Почему добавление дополнительного квалификатора const
"отбрасывает квалификаторы во вложенных типах указателей"?
Ответы
Ответ 1
Причина, по которой const
может быть добавлена только на один уровень, является тонкой и объясняется Вопрос 11.10 в FAQ comp.lang.c.
Вкратце рассмотрим этот пример, тесно связанный с вашим:
const int i;
int *p;
int const **z = &p;
*z = &i;
/* Now p points to i */
C избегает этой проблемы, только разрешая присваивание отбрасывать квалификаторы на первом указанном уровне (поэтому назначение z
здесь не допускается).
Ваш конкретный пример не страдает этой проблемой, потому что const
второй уровень означает, что присвоение *z
не будет разрешено в любом случае. С++ разрешил бы это в этом конкретном случае, но C более простые правила не различают ваш случай и пример выше.
Ответ 2
Ссылка на часто задаваемые вопросы, связанная с другим ответом, объясняет, почему следующий код не разрешен:
int **x = whatever;
const int **z = x;
Однако ваш код const int *const *z = x;
совсем другой, и он не страдает от того же недостатка, который возникает в FAQ.
Фактически, в последнем коде нет ничего неправильного. Это просто недостаток в спецификации C, что он не разрешен, и он заставляет программистов C включать уродливые броски в свой код.
Было бы возможно, чтобы C использовал те же правила, что и С++; однако стандартный комитет С не решил сделать это.