преобразование указателя в константу в C - PullRequest
4 голосов
/ 26 октября 2009

Следующий код компилируется без предупреждения в GCC, но выдает предупреждение в Visual Studio 2005.

const void * x = 0;
char * const * p = x;

x указывает на постоянный объект неизвестного типа, а p указывает на постоянный указатель на символ. Почему назначение p должно привести к предупреждению?

Опять же, это C, а не C ++. Спасибо.

Ответы [ 6 ]

5 голосов
/ 26 октября 2009

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

Итак, чтобы сообщить компилятору, что вы действительно собираетесь это сделать, вы должны выполнить явное приведение, например:

        const void * x = 0;
        char * const * p = (char * const * )x;

P.S. Во-первых, я написал: « в большинстве случаев делается непреднамеренно», но AndreyT заставил меня пересмотреть это, когда он справедливо сказал, что void * существует специально для этой цели.

3 голосов
/ 26 октября 2009

Код C действителен, и соответствующий компилятор не должен предупреждать, поскольку const ness правильно сохранен, и преобразование void * в любой тип указателя (кроме указателей на функции) неявно.

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

0 голосов
/ 29 октября 2009
const void * x = 0;
char * const * p = x;

Сначала я предположил, что вы хотели взять адрес x и написал код для этого. Тогда я решил, что x указывает на указатель на char []. В любом случае, и это все еще довольно запутанно:

#include <stdio.h>
int main()
{
        char s [] = "Hello World!";
        const void * x = s;
        const char * const * const p = (const char * const *)&x;
        printf("%s\n", *p);
/* won't compile
        *p++;      // increments x to point to 'e'
        (**p)++;   // increments 'H' to 'I'
*/
        const char * y = s;
        x = &y;
        const char * const * const q = x;
        printf("%s\n", *q);
/* won't compile
        *q++;
        (**q)++;
*/
        return 0;
}

Дополнительные const перед char в объявлении p предотвращают компиляцию (**p)++. Однако добавлено const до объявления q (в GCC) теней warning: dereferencing ‘void *’ pointer с error: increment of read-only location ‘**q’ для (**q)++. Надеюсь, это поможет, это немного помогло мне: -)

0 голосов
/ 26 октября 2009

Вы должны прочитать следующее справа налево.
char * const * p = x;

Например:
P указывает на константный указатель типа char.

0 голосов
/ 26 октября 2009
warning C4090: 'initializing' : different 'const' qualifiers

Вы не можете разыграть const void до char *const или даже char *. Разыменовывая p, теперь вы можете изменить *(char *)(*x). Это немного известная тонкость в отношении указателей на C.

Рабочий тип для p будет:

char const **p = x;

И да, я поставил const справа, как мужчина.

0 голосов
/ 26 октября 2009

Что если x будет указывать, скажем, на struct Thing, а не на char? В этом случае вы будете делать что-то с неопределенным поведением. GCC, как правило, позволяет вам делать это, поскольку предполагает, что вы достаточно умен, чтобы не выстрелить себе в ногу, но есть веская причина для предупреждения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...