Невозможно преобразовать из «unsigned char **» в «const unsigned char **», почему? [Дубликат]

Существует два способа доступа к свойствам объекта:

  • Точечная нотация: something.bar
  • Обозначение скобок: something['bar']

Значение между скобками может быть любым выражением. Поэтому, если имя свойства хранится в переменной, вы должны использовать нотацию в виде скобок:

var foo = 'bar';
something[foo];
// both x = something[foo] and something[foo] = x work as expected
33
задан Alex Shesterov 6 October 2013 в 15:49
поделиться

5 ответов

Из стандарта:

const char c = 'c';
char* pc;
const char** pcc = &pc;   // not allowed
*pcc = &c;
*pc = 'C';                // would allow to modify a const object
34
ответ дан AProgrammer 21 August 2018 в 10:27
поделиться

Здесь есть два правила:

  • Между T* и U* нет неявных отбрасываний, если T и U - разные типы.
  • Вы может лишить T* до T const * неявно. («указатель на T» можно отнести к «указателю на const T»). В C ++, если T также является указателем, это правило также может быть применено к нему (цепочка).

Итак, например:

char** означает: указатель на указатель на char.

И const char** означает: указатель на указатель на const char.

Поскольку указатель на char и указатель на const char имеют разные типы, которые не различаются только в const-ness, поэтому актерский состав не допускается. Правильный тип cast to должен быть const указателем на char.

Таким образом, чтобы оставаться const корректным, вы должны добавить ключевое слово const, начиная с самой правой звездочки.

Таким образом, char** может быть отличным до char * const * и также может быть добавлено к const char * const *.

Это цепочка только C ++. В C это цепочка не работает, поэтому на этом языке вы не можете корректно наложить более одного уровня указателей const.

6
ответ дан Calmarius 21 August 2018 в 10:27
поделиться

[h0] C ++ 11 draft standard объясняет это в примечании в разделе 4.4, в котором говорится:

[Примечание: если программа может назначить указатель типа T ** на указатель типа const T ** (то есть, если строка 1 ниже была разрешена), программа может непреднамеренно модифицировать объект const (как это делается в строке # 2). Например,

int main() {
const char c = 'c';
char* pc;
const char** pcc = &pc; // #1: not allowed
*pcc = &c;
*pc = 'C'; // #2: modifies a const object
}

-end note]

Интересным связанным вопросом является . Если int ** p1 и const int ** p2 есть p1 = = p2 хорошо сформирован? .

Обратите внимание, что в C ++ FAQ также есть объяснение, но мне больше нравится пояснение из стандарта.

Соответствующий текст, который идет с примечанием, выглядит следующим образом:

Преобразование может добавлять cv-квалификаторы на уровнях, отличных от первого в многоуровневых указателях, с соблюдением следующих правил: 56

Два типа указателей T1 и T2 аналогичны, если существует тип T и целое число n> 0, что:

T1 является cv1,0 указателем на cv1, 1 указатель на ··· cv1, n-1 указатель на cv1, n T

и

T2 - cv2,0 указатель на указатель cv2,1 to ··· cv2, n-1 указатель на cv2, n T

, где каждый cvi, j является const, volatile, const volatile или ничего. N-кортеж cv-квалификаторов после первого в типе указателя, например cv1,1, cv1,2, ..., cv1, n в типе указателя T1, называется cv-квалификационной сигнатурой типа указателя , Выражение типа T1 может быть преобразовано в тип T2 тогда и только тогда, когда выполняются следующие условия:

  • типы указателей аналогичны.
  • для каждого j> 0, если const находится в cv1, j, то const находится в cv2, j и аналогично для volatile.
  • , если cv1, j и cv2, j различны, то const находится в каждом cv2, k для 0 & lt; ; k & lt; j.
8
ответ дан Community 21 August 2018 в 10:27
поделиться
  • 1
    Большое спасибо. Прочитав ваш ответ пару раз, я наконец получил его! – Anton 24 March 2015 в 19:53
  • 2
    @AntonTugolukov выглядит так, как будто ваш вопрос был объединен с этим текущим – Shafik Yaghmour 25 July 2016 в 17:22

Игнорируя ваш код и отвечая на принцип вашего вопроса, см. эту запись в comp.lang.c FAQ: Почему я не могу передать char ** функции, которая ожидает const char **?

Причина, по которой вы не можете присвоить значение char ** указателю const char **, несколько неясна. Учитывая, что квалификатор const существует вообще, компилятор хотел бы помочь вам сохранить ваши обещания не изменять значения const. Вот почему вы можете назначить char * для const char *, но не наоборот: явно безопасно «добавить» const -ness к простому указателю, но было бы опасно его убрать. Однако предположим, что вы выполнили следующую более сложную серию заданий:

const char c = 'x';    /* 1 */
char *p1;              /* 2 */
const char **p2 = &p1; /* 3 */
*p2 = &c;              /* 4 */
*p1 = 'X';             /* 5 */

В строке 3 мы присваиваем char ** const char **. (Компилятор должен жаловаться.) В строке 4 мы присваиваем const char * const char *; это явно легально. В строке 5 мы модифицируем то, что указывает char * - это должно быть законным. Однако p1 заканчивается, указывая на c, который является const. Это произошло в строке 4, потому что *p2 был действительно p1. Это было установлено в строке 3, которая является назначением формы, которая запрещена, и именно поэтому строка 3 запрещена.

И как ваш вопрос помечен как C ++, а не C, он даже объясняет, что использовать следующие const квалификаторы:

(C ++ имеет более сложные правила для назначения указателей со знаком const, которые позволяют вам делать больше видов назначений без каких-либо предупреждений, но все же защищать от непреднамеренных попыток изменения значений const. C ++ все же не позволил бы присвоить char ** const char **, но это позволило бы вам уйти с назначением char ** в const char * const *.)

16
ответ дан jamesdlin 21 August 2018 в 10:27
поделиться

Так как никто не опубликовал решение , здесь:

char *s1 = 0;
const char *s2 = s1; // OK...
char *a[MAX]; // aka char **
const char * const*ps = a; // no error!

( http://www.parashift.com/c++-faq-lite/ const-correctness.html # faq-18.17 для почему)

11
ответ дан Potatoswatter 21 August 2018 в 10:27
поделиться
  • 1
    Следует отметить, что он не будет работать для C, только C ++. – Calmarius 26 June 2014 в 15:59
  • 2
    Вопрос не отмечен c . Есть ли другая причина для downvote? – Potatoswatter 26 March 2015 в 05:28
Другие вопросы по тегам:

Похожие вопросы: