2011-07-06 15 views
12

Tengo problemas para encontrar un patrón intuitivo para la forma en que se usa const en declaraciones en los lenguajes C y C++. He aquí algunos ejemplos:Entender dónde va "const" en una declaración

const int a; //Const integer 
int const a; //Const integer 
const int * a; //Pointer to constant integer 
int * const a; //Const pointer to an integer 
int const * a const; //Const pointer to a const integer 

En las líneas 1 y 2, parece const puede venir antes o después de int, que es lo que modifica.

  1. Entonces, ¿cómo, en la línea 4, el compilador qué deciden que está modificando const* (puntero) en lugar de int?
  2. ¿Cuál es la regla que sigue el compilador para decidir a qué se aplica el const?
  3. ¿Sigue la misma regla para *?
+9

enlace obligatorio a la [regla en espiral a la derecha] (http://c-faq.com/decl/spiral.anderson.html) –

+1

Si no hay matrices o funciones involucradas, simplemente ** leyendo de derecha a izquierda * * también puede ayudar: 'int const * const a':" 'a' es un puntero const a un const int". –

+0

Mark, si lo hubiera enviado como respuesta, lo habría comprobado. ¡Muy útil y realmente me ayuda a resolverlo! –

Respuesta

4

El compilador generalmente lee el tipo de derecha a izquierda, por lo que:

T const& const 

Would ser leído como:

const (a constant) 
& (to a reference) 
const (to a constant) 
T (of type T) 

Así que, básicamente, la palabra clave "const" modifica todo lo que le precede. Sin embargo, hay una excepción en el caso en que "const" es lo primero, en cuyo caso se modifica el artículo directamente a la derecha del mismo:

const T& const 

Lo anterior se lee como:

const (a constant) 
& (to a reference) 
const T (to a constant of type T) 

Y lo anterior es equivalente a T const & const.

Si bien esta es la forma en que el compilador lo hace, en realidad sólo recomiendo la memorización de los casos "T", "T const", "T const &", "const T *", "T const & const", "const T * const "," T & const "y" T * const ". Rara vez se encontrará con otra variación de "const", y cuando lo haga, probablemente sea una buena idea usar un typedef.

+0

Gracias por explicar cómo lo hace el compilador, no solo cómo "un humano puede hacerlo", que es realmente lo que estaba pidiendo. –

+5

Creo que no existe una "referencia constante" (o, en otras palabras, siempre son constantes). Entonces 'T & const' no es correcto semánticamente. VC++ 2010 da una advertencia e ignora el 'const'. Simplemente un recordatorio. :) – Nubcase

+1

-1 para el mal ejemplo. Deberías haber usado un puntero aquí, no una referencia. –

7

Suponiendo que siempre coloca const a la derecho del tipo, se puede leer una declaración de variable como una sentencia de derecha a izquierda:

int const x;  // x is a constant int 
int *const x;  // x is a constant pointer to an int 
int const *x;  // x is a pointer to a constant int 
int const *const x; // x is a constant pointer to a constant int 

Esto todavía funciona si pones const a la a la izquierda de un tipo, pero requiere un poco más de esfuerzo mental. Tenga en cuenta que esto funciona igual de bien con punteros a punteros (y constructos de orden superior):

int *const *const x; // x is a constant pointer to a constant pointer to an int 
+0

¡Pásame por 30 segundos! –

+1

Así que la regla básica se lee de derecha a izquierda, y si la que está más a la izquierda es 'const', entonces se aplica a la cosa directamente a su derecha. Así que 'const' se aplica a la cosa de la izquierda, a menos que no tenga nada a la izquierda, por lo que se aplica a la cosa de la derecha. –

2

Para los punteros, aquí hay uno que recogí de uno de los libros de Scott Meyers (creo). Dibuja una línea vertical a través del *, y luego lo que esté en el mismo lado de la línea que la palabra clave const es lo que está const.

Para aclarar:

int * const a significa que a es constante, no es el int. Y "a" es un puntero al int (no const).

0

Bueno, para empezar, esta pregunta es más una preferencia personal. Para el programador de ocio, es más un estilo personal. Sin embargo, para aquellos que se ocupan de corporaciones, puede haber algún tipo de convención de codificación que los diseñadores puedan seguir para que todos puedan usar estilos de codificación coherentes.

(1) Para const int * const a; significa que no puede cambiar a lo que apunta su puntero pero puede modificar esa ubicación de memoria.

(2) El 'const' lo decide usted, como el programador, si desea que la dirección a la que apunta el puntero sea constante o si desea que el puntero NO modifique el puntero al que apunta.

(3) Si las reglas son las mismas para * como en el caso de const int * const a;

Como nota adicional, su última línea no es válida C89.

Espero que ayude. ¡Aclamaciones!

+0

Puede ser una preferencia para el programador, pero definitivamente no para el otro tipo que tiene que leer su código. –

+0

El problema no está solo en escribirlos, sino también en leer uno que otro escribió. –

+0

De acuerdo. ¡Aclamaciones! :) – Vern

1

La clave para entender esto es darse cuenta de que el * se une al a, no al tipo. Por lo tanto, debe leerlos como:

const int a; // a has type const int 
int const a; // a has type int const 
const int * a; // *a has type const int 
int * const a; // *(const a) has type int, which means *a has type int and a is const 
int const * a const; // *(const a) has type int const, which means *a has type const int and a is const. 

(Tenga en cuenta que las referencias de C++ no siguen esta regla).

Cuestiones relacionadas