que - ¿Podemos cambiar el valor de un objeto definido con const a través de punteros?
punteros constantes (10)
#include <stdio.h>
int main()
{
const int a = 12;
int *p;
p = &a;
*p = 70;
}
¿Funcionará?
Aquí el tipo de puntero p
es int*
, al que se le está asignando el valor de tipo const int*
( &a
=> dirección de una variable const int
).
El molde implícito elimina la constness, aunque gcc lanza una advertencia (tenga en cuenta que esto depende en gran medida de la implementación).
Como el puntero no está declarado como const
, el valor se puede cambiar usando dicho puntero.
si el puntero se declarara como const int* p = &a
, no podrá hacer *p = 70
.
De hecho, funciona con gcc. Aunque no me gustó:
test.c: 6: warning: la tarea descarta los calificadores del tipo de destino del puntero
Pero el valor cambió cuando se ejecutó. No señalaré el obvio no-no ...
Es un "comportamiento indefinido", lo que significa que, según el estándar, no puedes predecir qué sucederá cuando pruebes esto. Puede hacer diferentes cosas dependiendo de la máquina en particular, el compilador y el estado del programa.
En este caso, lo que sucederá más a menudo es que la respuesta será "sí". Una variable, const o no, es solo un lugar en la memoria, y puede romper las reglas de constness y simplemente sobrescribirlo. (Por supuesto, esto causará un error grave si alguna otra parte del programa depende de que sus datos sean constantes).
Sin embargo, en algunos casos, más típicamente para datos const static
, el compilador puede poner tales variables en una región de memoria de solo lectura. MSVC, por ejemplo, generalmente coloca las entradas estáticas en el segmento .text del archivo ejecutable, lo que significa que el sistema operativo generará un error de protección si intentas escribir en él, y el programa se bloqueará.
En alguna otra combinación de compilador y máquina, puede pasar algo completamente diferente. Lo único que puede predecir con certeza es que este patrón molestará a quien tenga que leer su código.
Es un comportamiento indefinido. Prueba:
/* program.c */
int main()
{
const int a = 12;
int* p;
p = &a;
*p = 70;
printf("%d/n", a);
return 0;
}
gcc program.c
y ejecutarlo. La producción será 70 (gcc 4.3)
Entonces compilarlo así:
gcc -O2 program.c
y ejecutarlo. El resultado será 12. Cuando se optimiza, el compilador presumiblemente carga 12 en un registro y no se molesta en cargarlo nuevamente cuando necesita acceder a a para la impresión porque "sabe" que a no puede cambiar.
Este código contiene una violación de restricción :
const int a = 12;
int *p;
p = &a;
La restricción violada es C11 6.5.16.1/1 "Asignación simple"; si ambos operandos son punteros, entonces el tipo al que apunta la izquierda debe tener todos los calificadores del tipo al que apunta la derecha. (Y los tipos, sin calificadores, deben ser compatibles).
Entonces la restricción se viola porque &a
tiene tipo const int *
, que tiene const
como calificador; pero ese calificador no aparece en el tipo de p
que es int *
.
El compilador debe emitir un diagnóstico y no generar un ejecutable. El comportamiento de cualquier ejecutable sería completamente indefinido, ya que el programa no cumple con las reglas del lenguaje.
La modificación de un objeto const
calificado a través de un puntero invoca un comportamiento indefinido, y tal es el resultado. Sin embargo, es probable que sea algo que esperarías, es decir. el valor anterior sin cambios, si se ha colocado en .text
, etc.
Mala, MALA idea.
Además, el comportamiento es específico de la plataforma y la implementación. Si se está ejecutando en una plataforma donde la constante se almacena en una memoria no grabable, obviamente no funcionará.
Y, ¿por qué demonios querrías? Actualice la constante en su fuente o conviértala en una variable.
No puede cambiar el valor de una variable constante utilizando un puntero que apunta a ella. Este tipo de puntero se denomina Pointer to a constant
.
También hay otro concepto llamado Constant Pointer
. Significa que una vez que un puntero apunta a una ubicación de memoria no puede hacer que apunte a la otra ubicación.
Sí, puedes cambiar el valor de una variable constante.
Prueba este código:
#include <stdio.h>
int main()
{
const int x=10;
int *p;
p=(int*)&x;
*p=12;
printf("%d",x);
}
sí, puedes hacerlo usando dicho código. pero el código no se aplica cuando cuando a
es global (un programa compilado por gcc me dio un segmentation fault
)
en términos generales, en la querida C, casi siempre puedes encontrar de alguna manera para hackear cosas que no se supone que deben ser cambiadas o expuestas. const aquí es un ejemplo.
Pero pensando en el pobre tipo (tal vez yo mismo después de 6 meses) mantiene nuestro código, a menudo elijo no hacerlo.