¿Por qué son válidos tanto "const T" como "T const" y cuál debería utilizar?

Resuelto AJG85 asked hace 13 años • 9 respuestas

Para empezar, probablemente sepa que constse puede utilizar para hacer que los datos de un objeto o un puntero no sean modificables, o ambos.

const Object* obj; // can't change data
Object* const obj; // can't change pointer
const Object* const obj; // can't change data or pointer

Sin embargo, también puedes utilizar la sintaxis:

Object const *obj; // same as const Object* obj;

Lo único que parece importar es en qué lado del asterisco pones la constpalabra clave. Personalmente, prefiero colocarlo consta la izquierda del tipo para especificar que sus datos no se pueden modificar, ya que creo que se lee mejor en mi mentalidad de izquierda a derecha, pero ¿qué sintaxis apareció primero?

Más importante aún, ¿por qué existen dos formas correctas de especificar constdatos y en qué situación preferiría o necesitaría una sobre la otra, si corresponde?

Editar

Entonces parece que fue una decisión arbitraria cuando el estándar sobre cómo los compiladores deberían interpretar las cosas se redactó mucho antes de que yo naciera. Dado que constse aplica a lo que está a la izquierda de la palabra clave (¿de forma predeterminada?), Supongo que pensaron que no había ningún daño en agregar "atajos" para aplicar palabras clave y escribir calificadores de otras maneras, al menos hasta el momento en que la declaración cambie por analizando un *o &...

Supongo que este también fue el caso en C.

AJG85 avatar Mar 31 '11 23:03 AJG85
Aceptado

¿Por qué hay dos formas correctas de especificar constdatos y en qué situación preferiría o necesitaría una sobre la otra, si corresponde?

Esencialmente, la razón por la que la posición constdentro de los especificadores antes de un asterisco no importa es que Kernighan y Ritchie definieron la gramática C de esa manera.

La razón por la que definieron la gramática de esta manera fue probablemente que su compilador de C analizaba la entrada de izquierda a derecha y terminaba de procesar cada token a medida que lo consumía. El consumo del *token cambia el estado de la declaración actual a un tipo de puntero. Encontrar constafter *significa que el constcalificador se aplica a una declaración de puntero; encontrarlo antes de *que el calificador se aplique a los datos señalados.

Debido a que el significado semántico no cambia si el constcalificador aparece antes o después de los especificadores de tipo, se acepta de cualquier manera.

Un caso similar surge al declarar punteros de función, donde:

  • void * function1(void)declara una función que devuelve void *,

  • void (* function2)(void)declara un puntero de función a una función que devuelve void.

Una vez más, lo que hay que tener en cuenta es que la sintaxis del lenguaje admite un analizador de izquierda a derecha.

Heath Hunnicutt avatar Mar 31 '2011 16:03 Heath Hunnicutt

La regla es:

const se aplica a lo que queda de él. Si no hay nada a la izquierda, entonces se aplica a lo que está a la derecha.

Prefiero usar const a la derecha de la cosa para que sea constante solo porque es la forma "original" en que se define const.

Pero creo que este es un punto de vista muy subjetivo.

horstforst avatar Mar 31 '2011 16:03 horstforst

Prefiero la segunda sintaxis. Me ayuda a realizar un seguimiento de "qué" es constante leyendo la declaración de tipo de derecha a izquierda:

Object * const obj;        // read right-to-left:  const pointer to Object
Object const * obj;        // read right-to-left:  pointer to const Object
Object const * const obj;  // read right-to-left:  const pointer to const Object
Matt Davis avatar Mar 31 '2011 17:03 Matt Davis

El orden de las palabras clave en una declaración no es tan fijo. Hay muchas alternativas al "único orden verdadero". Como esto

int long const long unsigned volatile i = 0;

o debería ser

volatile unsigned long long int const i = 0;

??

Bo Persson avatar Mar 31 '2011 17:03 Bo Persson