2010-09-27 4 views
25
#include <stdio.h> 
int main() 
{ 
    const int a = 12; 
    int *p; 
    p = &a; 
    *p = 70; 
} 

¿Funcionará?¿Podemos cambiar el valor de un objeto definido con const a través de punteros?

+2

muchos duplicados, por ejemplo, [constantes y punteros en C] (http://stackoverflow.com/questions/945640/constants-and-pointers-in-c) –

+0

Quizás pueda intentar utilizar un puntero de puntero para acceder a la const int a. '* (int *) p = 70;' – 1020rpz

+0

Posible duplicado de [¿Por qué puedo cambiar una variable local const mediante moldes de puntero pero no uno global en C?] (Http://stackoverflow.com/questions/945640/why-can-i-change-a-local-const-variable-through-pointer-castts-but-not-a-global-o) –

Respuesta

27

Es un "comportamiento indefinido", lo que significa que, basado en el estándar, no se puede predecir qué sucederá cuando intentes 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 provocará un error grave si alguna otra parte del programa depende de que sus datos const sean constantes!)

Sin embargo, en algunos casos, más típicamente para datos const static, el compilador puede poner dichas 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.

+0

Intenté codein ideone similar y se bloqueó. ¿Hay un método confiable para realmente cambiar la variable? –

+0

Como el valor se supone constante, el compilador también puede optimizar los accesos a la memoria utilizando el valor como un valor inmediato en una instrucción en lugar de usar una instrucción de carga adicional para recuperarla de la memoria. De modo que puede obtener muchos estados extraños aquí: la variable fue eliminada por completo por el optimizador, utiliza en algunos lugares la variable de referencia, pero en otros lugares usa una inmediata (que su truco no cambió), etc. (Estoy no estoy seguro de qué tan probable es que la const solo sea * parcialmente * cambiada a una inmediata, pero estoy bastante seguro de que es posible el reemplazo inmediato). – zstewart

5

De hecho, funciona con gcc. No le gustaba que sin embargo:

test.c: 6: advertencia: la asignación descarta clasificados de puntero del tipo de destino

Pero el valor sí cambió cuando se ejecuta. No señalaré el obvio no-no ...

0

No puede cambiar el valor de una variable constante utilizando un puntero que apunta hacia ella. Este tipo de puntero se llama como 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.

+0

pero el valor cambió cuando ejecuto este código – Shweta

10

La modificación de un objeto calificado const 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.

+4

Otro posible resultado es "algunas expresiones se comportan como si 'a' fuera todavía 12, mientras que otras se comportan como si 'a' ahora es 70", lo que puede o no ser "algo que 'esperar' – caf

3

sí, puede hacerlo utilizando dicho código. pero el código no se aplican cuando cuando a es mundial (un programa gcc-compilado me dio segmentation fault.)

en términos generales, en la amada C, casi siempre se puede encontrar alguna manera de cortar las cosas que no se supone que ser cambiado o expuesto. const aquí es un ejemplo.

Pero pensando en el pobre chico (tal vez yo mismo después de 6 meses) mantiene nuestro código, a menudo elijo no hacerlo.

1

Aquí el tipo de puntero p es int*, que está siendo asignado 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 utilizando dicho puntero.

si el puntero se declararía como const int* p = &a, no podrá hacer *p = 70.

12

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 ejecútelo. La salida será 70 (gcc 4.3)

a continuación, compilar esta manera:

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.

+7

Es curioso, cuando ejecuto este programa, la salida es 42. – abelenky

+4

@abelenky: sí, pero ¿se detuvo a pensar cuál es la pregunta? Tal vez deberías construir una computadora para averiguarlo. – JeremyP

+0

El hecho de que gcc se comporte de manera extraña dado un fragmento de código solo significa que el código invoca Comportamiento no definido si gcc confirmó el estándar en todos los casos. En la práctica, sin embargo, gcc es incapaz de manejar eficientemente cierta semántica requerida de un compilador conforming, y en vez de manejarlos de una manera que sea conforme pero ineficaz, o arreglar su modelo de ejecución para manejarlos de manera eficiente y conforme, manera, gcc ops para manejarlos de una manera que sea "eficiente" pero rota y no conforme. – supercat

0

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é querrías? Actualice la constante en su fuente o conviértala en una variable.

-1

Sí, puede cambiar el valor de una variable constante.
probar este código:

#include <stdio.h> 

int main() 
{ 
    const int x=10; 

    int *p; 
    p=(int*)&x; 
    *p=12; 
    printf("%d",x); 
} 
Cuestiones relacionadas