Conversión implícita de char ** a const char **

¿Por qué mi comstackdor (GCC) no emite implícitamente de char** a const char** ?

El siguiente código:

 #include  void print(const char** thing) { std::cout << thing[0] << std::endl; } int main(int argc, char** argv) { print(argv); } 

Da el siguiente error:

 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] 

Tal conversión le permitiría poner un const char* en su matriz de char* , lo que sería inseguro. En forma print , podrías hacer:

 thing[0] = "abc"; 

Ahora argv[0] apuntaría a un literal de cadena que no se puede modificar, mientras que main espera que sea no const ( char* ). Por lo tanto, para la seguridad del tipo, esta conversión no está permitida.

El enlace de @Fred Overflow a las preguntas frecuentes es una respuesta completa. Pero (lo siento Marshall) no es la explicación más clara. No sé si el mío es más claro, pero espero que sí.


El problema es que si p es un puntero char* , puede usarse para modificar lo que apunta.

Y si pudiera obtener un puntero pp que apunte a p , pero con pp de tipo char const** , entonces podría usar pp para asignar a p la dirección de un const char .

Y con eso, podrías usar p para modificar el const char . O, pensarías que podrías. Pero ese const char incluso podría estar en la memoria de solo lectura …

En codigo:

 char const c = 'a'; char* p = 0; char const** pp = &p; // Not allowed. :-) *pp = &c; // p now points to c. *p = 'b'; // Uh oh. 

Como una solución práctica para su código que no comstack, …

 #include  void print(const char** thing) { std::cout << thing[0] << std::endl; } int main(int argc, char** argv) { print(argv); // Dang, doesn't compile! } 

solo haz …

 #include  void print( char const* const* thing ) { std::cout << thing[0] << std::endl; } int main( int argc, char** argv ) { print( argv ); // OK. :-) } 

Saludos y hth.,

Tenga en cuenta que, aunque

 void dosmth(const char** thing); int main(int argc, char** argv) { dosmth(argv); 

está prohibido, puedes y deberías hacer

 void dosmth(const char* const* thing); int main(int argc, char** argv) { dosmth(argv); 

Que es probablemente lo que querías de todos modos. El punto aquí es que ahora se refiere a una matriz const char* que es inmutable en sí misma y cuyos valores de referencia son inmutables. Por lo tanto, para un escenario de ” míralo, pero no lo cambies “, const char* const* es el tipo que se usará.

Nota: utilicé el estándar más común (pero en mi opinión inferior) de intentar escribir el modificador const más izquierdo posible. Personalmente, recomiendo escribir char const* const* lugar de const char* const* ya que es mucho más conciso de esa manera.

Porque podría permitirnos modificar un valor constante. Lea aquí para comprender por qué: http://c-faq.com/ansi/constmismatch.html