2011-10-25 25 views
7

¿Cómo hace un compilador, C o C++, (por ejemplo, gcc) la declaración const?¿Cómo se implementa "const"?

Por ejemplo, en el código siguiente, ¿Cómo funciona el compilador no pierde de vista que la variableci es const y no se puede modificar?

int 
get_foo() { 
    return 42; 
} 

void 
test() 
{ 
    int i = get_foo(); 
    i += 5; 

    const int ci = get_foo(); 
    // ci += 7; // compile error: assignment of read-only variable ?ci? 
} 
+5

De la misma manera se realiza un seguimiento de toda la información en tiempo de compilación sobre var Ibles? –

+0

Se realiza en tiempo de compilación a través del sistema de tipo. –

+1

Su comentario debería decir "asignación a variable de solo lectura". Por cierto, ¿cómo crees que el compilador sabe que es un número entero? – hplbsh

Respuesta

9

Mucho como cualquier otro bit de información de símbolos para las variables (dirección, tipo, etc.). Por lo general, hay una tabla de símbolos que almacena información sobre los identificadores declarados, y esto se consulta cada vez que encuentra otra referencia al identificador.

(Una cuestión más interesante es si este conocimiento sólo está presente durante la compilación o incluso durante el tiempo de ejecución. La mayoría de los idiomas descartan la tabla de símbolos después de compilar, por lo que puede manipular el código compilado y forzar un nuevo valor, incluso si el identificador se declaró 'const'. se necesita un sofisticado sistema de tiempo de ejecución (y la firma de código) para evitar eso.)

+0

Para agregar a esto, un C++/C Compiler de problema estándar no hace mucho si mantiene una variable como esta "const" en tiempo de ejecución, simplemente sabe que no generará ningún código que pueda modificar este valor a través de la tabla de símbolos Kilian mencionó. Consecuentemente, algún otro compilador podría crear algún código y si ese código se cargara en el proceso, podría sobrescribir la memoria en esa ubicación. Eso es malo. – Dlongnecker

+1

Los datos de Const se pueden colocar dentro de un bloque de memoria diferente y en algunos sistemas ese bloque de memoria se marcará como de solo lectura. Al igual que el código en sí reside en un segmento diferente (tal vez los datos y el código const pueden ser mixtos). Por supuesto, esto solo se aplica a consts estáticos y nada creado en la pila. –

1

El compilador sabe que es ciconst porque usted le dijo que por lo que con la línea

const int ci = get_foo(); 

Al pasar ci torno a otras funciones o le asigne a otras variables, el compilador conserva que const- ness al evitar que haga algo que potencialmente podría cambiar su valor.

Por ejemplo, lo siguiente produce un error de compilación.

int *ci2 = &ci; 
(*ci2)++; 

Porque el compilador no le permite modificar el valor de ci.

+0

Su último ejemplo debería producir un error de compilación incluso sin la operación de incremento. No se puede asignar un valor de puntero a const a una variable de puntero a no const. – Novelocrat

3

Por supuesto, es la implementación de cada compilador, pero en pocas palabras, se almacena const y volatile fase de clasificación de la variable (si lo hay) en su tabla de símbolos variables, junto con otra información como el tipo de la variable y si es o no es un puntero/referencia.

+0

"Calificadores CV"? ¡Seguramente las variables no tienen curriculum vitae! – Gabe

+1

@Gabe: el estándar habla mucho sobre ellos (const/volátil) en la sección 3.9.3 "Calificadores de CV". –

1

Estoy seguro de que otros pueden dar más detalles, pero en resumen, sí. El compilador realiza un seguimiento de todos los especificadores de tipo para que sepa que ci es del tipo "const int" y no "int".

1

Como han dicho otros, const es seguido por el compilador de la misma manera que el compilador rastrea el hecho de que una variable es un int. De hecho, he leído que al menos gcc considera const int un tipo distinto de int, por lo que ni siquiera se rastrea como modificador, se rastrea de la misma manera que un int.

Tenga en cuenta que en realidad se puede cambiar el valor de una const a través de fundición puntero, pero el resultado es indefinido:

#include <stdio.h> 
#include <stdlib.h> 

int main(void) { 
     const int c = 0; 
     printf("%d\n", c); 
     ++*(int*)&c; 
     printf("%d\n", c); 
} 

En mi máquina se utiliza gcc, esto imprime

0 
1 

Pero compilar con g ++ da

0 
0