Потому что технически вы можете разорвать обещание, передав неконстантную указатель на константный указатель параметра.
«Опасно отнимать константный-Несс»
http://c-faq.com/ansi/constmismatch.html
Вот содержание приведенной выше ссылке:
Вы можете использовать указатель на T (для любой тип T), где ожидается указатель на const-T. Однако правило (явное исключение), которое допускает небольшие несоответствия в квалифицированных типах указателей, не применяется рекурсивно, а только на верхнем уровне. (const char ** является указателем на указатель на const-char, и поэтому исключение не применяется.)
Причина, по которой вы не можете присвоить значение char ** указателю const char ** несколько неясным. Учитывая, что спецификатор const существует вообще, компилятор хотел бы помочь вам сохранить ваши обещания не изменять значения const. Вот почему вы можете назначить char * для const char *, но не наоборот: явно безопасно «добавить» константу к простому указателю, но было бы опасно забрать его. Однако предположим, что вы выполнили следующую более сложную серию заданий:
const char c = 'x'; /* 1 */
char *p1; /* 2 */
const char **p2 = &p1; /* 3 */
*p2 = &c; /* 4 */
*p1 = 'X'; /* 5 */
В строке 3 мы задаём полукокс ** к константному гольцу **. (Компилятор должен жаловаться.) В строке 4 мы присваиваем const char * const char *; это явно легально. В строке 5 мы модифицируем то, что указывает символ *, - это должно быть законным. Однако p1 заканчивается, указывая на c, который является константой. Это произошло в строке 4, потому что * p2 действительно был p1. Это было установлено в строке 3, которая является назначением формы, которая запрещена, и именно поэтому строка 3 запрещена.
Назначение символа char ** const char ** (как в строке 3, так и в исходном вопросе) не является непосредственной опасностью. Но это создает ситуацию, в которой обещание p2 - то, что значение в конечном счете не будет изменено, не может быть сохранено.
(C++ имеет более сложные правила для назначения указателей со спецификацией const, которые позволяют вам делать больше видов назначений без возникновения предупреждений, но все же защищать от непреднамеренных попыток изменения значений const. C++ все равно не разрешил бы присвоение char ** a const char **, но это позволит вам уйти с назначением char ** для константы char * const *.)
В C, если вы должны назначить или передать указатели, которые имеют несоответствия квалификатора, отличные от первый уровень косвенности, вы должны использовать явные приведения (например, (const char **) в этом случае), хотя, как всегда, необходимость такого приведения может указывать на более глубокую проблему, которую отливка действительно не исправляет.
Это довольно хороший пример, который вы мне дадите.Я думаю, что кастинг - мое единственное решение здесь. – Phong
Я уверен, что все согласятся с тем, что опасно отбирать сочувствие. Однако этот случай является добавлением константы. В любом случае, связанный FAQ дает ответ. Было бы полезно привести суть этого ответа в этот ответ, чтобы этот ответ не был ответом «только для ссылок». –
@CraigMcQueen: Спасибо за комментарий. (Я могу опаздывать), но я обновил ответ, чтобы включить содержание ссылки – Phong