Вопрос такой, почему один код выдает "Значение типа char(*)[4] нельзя использовать для инициализации сущности типа char**"
char a[] = "abc";
char** cpp = &a;
а другой код проходит
char a[] = "abc";
char* cp = a;
char** cpp = &cp;
И подвопрос - круглые скобки в char(*)[4] играют какую-то роль?
Во втором случае вы сначала делаете указатель, а потом указатель на указатель. char* cp=a; в принципе равносильно char* cp=&a[0]; Собственно именно по этому первый вариант не работает. Круглые скобки показывают нам, что это указатель на массив чаров.
В языке С++ переменную типа T можно инициализировать только значением типа T или значением, неявно приводимым к типу T.
Значение &a имеет тип char (*)[4] и не может быть использовано для инициализации указателя типа char **. Это разные, неприводимые типы, никакого отношения друг к другу не имеющие.
Значение &cp имеет тип char ** и может быть использовано для инициализации указателя типа char **. Это одинаковые типы
Вот и все. Вам компилятор все подробно расписал.
Скобки в char (*)[4] роль играют. char (*)[4] и char *[4] - разные типы.
Несмотря на то, что в некоторых случаях массив может быть интерпретирован компилятором как адрес своего первого элемента - он не является адресом первого элемента.
На рисунке ниже показан массив a и указатель на его первый элемент cp:
Когда вы пишете &a - вы получаете указатель на массив. Когда вы пишете &cp - вы получаете указатель на указатель. Массив не является указателем, поэтому эти два типа неприводимы друг к другу.
Массив такой же обьект, как и все остальные. Массив содержит в себе некоторое количество обьектов одного типа. Его имя используется точно также, как и адрес его первого элемента, что дает возможность передать массив по ссыльке, а это означает, что при определении:
char* cp = a;
указатель cp указывает на первый элемент массива, или, другими словами, содержит адрес первого элемента массива. Когда известен адрес первого элемента, есть возможность работать со всей последовательностью...
Но &a это адрес обьекта_массива имеющий тип char(*)[4], т.е. указатель на массив символов с четыремя элеметами типа char, а не указатель на адрес обьекта типа char(указатель на указатель). Точно также можно написать:
std::vector<char> a;
char* pv = &a[0]; // адрес первого элемента последовательности
char** pp = &pv; // адрес указателья
Но нельзя:
char** ppv = &a;
поскольку &a это std::vector<char>*, и никак не может преобразиться в char**. P.S. Разница только в том, что имя вектора не интерпретируется как адрес первого элемента посдеовательности
Сборка персонального компьютера от Artline: умный выбор для современных пользователей