Неявное преобразование из char ** в const char **
Почему мой компилятор (GCC) не скрывает от char**
до const char**
?
Следующий код:
#include <iostream>
void print(const char** thing) {
std::cout << thing[0] << std::endl;
}
int main(int argc, char** argv) {
print(argv);
}
Дает следующую ошибку:
oi.cpp: In function ‘int main(int, char**)’:
oi.cpp:8:12: error: invalid conversion from ‘char**’ to ‘const char**’ [-fpermissive]
oi.cpp:3:6: error: initializing argument 1 of ‘void print(const char**)’ [-fpermissive]
Ответы
Ответ 1
Такое преобразование позволит вам помещать const char*
в ваш массив char*
, что было бы небезопасно. В print
вы можете сделать:
thing[0] = "abc";
Теперь argv[0]
будет указывать на строковый литерал, который нельзя изменить, а main
ожидает, что он будет не const (char*
). Поэтому для безопасности типа это преобразование не допускается.
Ответ 2
@Fred Overflow ссылка на часто задаваемые вопросы - это полный ответ. Но (извините Маршалла) это не самое ясное объяснение. Я не знаю, насколько ясен, но надеюсь.
Дело в том, что если p
является указателем char*
, тогда его можно использовать для изменения того, на что он указывает.
И если бы вы могли получить указатель pp
, который указывает на p
, но с pp
типа char const**
, то вы можете использовать pp
для назначения p
адреса a const char
.
И с этим вы можете использовать p
для изменения const char
. Или, вы могли бы подумать, что могли бы. Но что const char
может быть даже в памяти только для чтения & hellip;
В коде:
char const c = 'a';
char* p = 0;
char const** pp = &p; // Not allowed. :-)
*pp = &c; // p now points to c.
*p = 'b'; // Uh oh.
Как практическое решение для вашего кода, который не компилируется, & hellip;
#include <iostream>
void print(const char** thing) {
std::cout << thing[0] << std::endl;
}
int main(int argc, char** argv) {
print(argv); // Dang, doesn't compile!
}
просто сделай & hellip;
#include <iostream>
void print( char const* const* thing )
{
std::cout << thing[0] << std::endl;
}
int main( int argc, char** argv )
{
print( argv ); // OK. :-)
}
Приветствия и hth.,
Ответ 3
Обратите внимание, что хотя
void dosmth(const char** thing);
int main(int argc, char** argv) {
dosmth(argv);
запрещено, вы можете и должны делать
void dosmth(const char* const* thing);
int main(int argc, char** argv) {
dosmth(argv);
Скорее всего, это то, что вы хотели. Дело здесь в том, что thing
теперь относится к массиву const char*
, который сам по себе является неизменным и которые ссылаются на значения char
сами по себе неизменяемы.
Итак, для "взглянуть на него, но не меняйте его", const char* const*
- это тип, который нужно использовать.
Примечание. Я использовал более общий (но, по моему мнению, худший) стандарт, пытающийся написать модификатор const
как можно более левым. Лично я рекомендую писать char const* const*
вместо const char* const*
, так как это намного более кратким.
Ответ 4
Потому что это может позволить нам изменить постоянное значение. Читайте здесь, чтобы понять, почему: http://c-faq.com/ansi/constmismatch.html