¿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