Solución:
Tuve este mismo problema hace unos años y me molestó muchísimo.
Las reglas en C se establecen de manera más simple (es decir, no enumeran excepciones como convertir char**
para const char*const*
). Consecuencia, simplemente no está permitido. Con el estándar C ++, incluyeron más reglas para permitir casos como este.
Al final, es solo un problema en el estándar C. Espero que el próximo estándar (o informe técnico) aborde este tema.
Para que se considere compatible, el puntero de origen debe ser constante en el nivel de direccionamiento indirecto inmediatamente anterior. Entonces, esto le dará la advertencia en GCC:
char **a;
const char* const* b = a;
Pero esto no lo hará:
const char **a;
const char* const* b = a;
Alternativamente, puedes lanzarlo:
char **a;
const char* const* b = (const char **)a;
Necesitaría la misma conversión para invocar la función f () como mencionó. Hasta donde yo sé, no hay forma de hacer una conversión implícita en este caso (excepto en C ++).
Sin embargo, en C puro, esto todavía da una advertencia, y no entiendo por qué
Ya ha identificado el problema; este código no es correcto const. “Const correcta” significa que, a excepción de const_cast
y yesos estilo C que eliminan const
, nunca puedes modificar un const
objeto a través de esos punteros o referencias constantes.
El valor de const
-corrección – const
existe, en gran parte, para detectar errores del programador. Si declaras algo como const
, está afirmando que no cree que deba modificarse, o al menos, aquellos con acceso a la const
La versión única no debería poder modificarla. Considerar:
void foo(const int*);
Como se declaró, foo
no tiene permiso para modificar el entero apuntado por su argumento.
Si no está seguro de por qué el código que publicó no const
-correcto, considere el siguiente código, solo ligeramente diferente del código de HappyDude:
char *y;
char **a = &y; // a points to y
const char **b = a; // now b also points to y
// const protection has been violated, because:
const char x = 42; // x must never be modified
*b = &x; // the type of *b is const char *, so set it
// with &x which is const char* ..
// .. so y is set to &x... oops;
*y = 43; // y == &x... so attempting to modify const
// variable. oops! undefined behavior!
cout << x << endl;
No-const
Los tipos solo pueden convertir a tipos constantes de formas particulares para evitar cualquier elusión de const
en un tipo de datos sin una conversión explícita.
Objetos declarados inicialmente const
son particularmente especiales: el compilador puede asumir que nunca cambian. Sin embargo, si b
se le puede asignar el valor de a
sin un yeso, podría intentar modificar inadvertidamente un const
variable. Esto no solo rompería la verificación que le pidió al compilador que hiciera, para no permitirle cambiar el valor de las variables, sino que también le permitiría romper las optimizaciones del compilador.
En algunos compiladores, esto se imprimirá 42
, en algunos 43
y otros, el programa se bloqueará.
Editar-agregar:
HappyDude: Tu comentario es acertado. O el lenguaje C, o el compilador de C que estás usando, trata const char * const *
fundamentalmente diferente a como lo trata el lenguaje C ++. Quizás considere silenciar la advertencia del compilador solo para esta línea fuente.