Подтвердить что ты не робот

Предупреждения о двойной ошибке указателя в 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 "отбрасывает квалификаторы во вложенных типах указателей"?

4b9b3361

Ответ 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 использовал те же правила, что и С++; однако стандартный комитет С не решил сделать это.