¿Cuál es la diferencia entre const int*, const int * const e int const *?
Siempre me equivoco sobre cómo usar const int*
, const int * const
y int const *
correctamente. ¿Existe un conjunto de reglas que definan lo que se puede y lo que no se puede hacer?
Quiero saber todo lo que se debe y no se debe hacer en términos de asignaciones, paso a funciones, etc.
Léalo al revés (según lo indicado por la regla en sentido horario/espiral ):
int*
- puntero a intint const *
- puntero a constante intint * const
- puntero constante a intint const * const
- puntero constante a constante int
Ahora el primero const
puede estar a cualquier lado del tipo así:
const int *
==int const *
const int * const
==int const * const
Si quieres volverte realmente loco puedes hacer cosas como esta:
int **
- puntero a puntero a intint ** const
- un puntero constante a un puntero a un intint * const *
- un puntero a un puntero constante a un intint const **
- un puntero a un puntero a un int constanteint * const * const
- un puntero constante a un puntero constante a un int- ...
Si alguna vez no está seguro, puede utilizar una herramienta como cdecl+ para convertir declaraciones en prosa automáticamente.
Para asegurarnos de que tenemos claro el significado de const
:
int a = 5, b = 10, c = 15;
const int* foo; // pointer to constant int.
foo = &a; // assignment to where foo points to.
/* dummy statement*/
*foo = 6; // the value of a can´t get changed through the pointer.
foo = &b; // the pointer foo can be changed.
int *const bar = &c; // constant pointer to int
// note, you actually need to set the pointer
// here because you can't change it later ;)
*bar = 16; // the value of c can be changed through the pointer.
/* dummy statement*/
bar = &a; // not possible because bar is a constant pointer.
foo
es un puntero variable a un número entero constante. Esto le permite cambiar lo que señala pero no el valor que señala. La mayoría de las veces, esto se ve con cadenas de estilo C donde tienes un puntero a un archivo const char
. Puede cambiar la cadena a la que apunta, pero no puede cambiar el contenido de estas cadenas. Esto es importante cuando la cadena en sí está en el segmento de datos de un programa y no debe cambiarse.
bar
es un puntero constante o fijo a un valor que se puede cambiar. Esto es como una referencia sin el azúcar sintáctico adicional. Debido a este hecho, normalmente usaría una referencia donde usaría un T* const
puntero a menos que necesite permitir NULL
punteros.
Para aquellos que no conocen la regla en sentido horario/espiral: comience desde el nombre de la variable, muévase en el sentido de las agujas del reloj (en este caso, retroceda) hasta el siguiente puntero o escriba . Repita hasta que termine la expresión.
Aquí hay una demostración:
Creo que todo ya está respondido aquí, pero solo quiero agregar que debes tener cuidado con typedef
los s. NO son sólo reemplazos de texto.
Por ejemplo:
typedef char *ASTRING;
const ASTRING astring;
El tipo de astring
es char * const
, no const char *
. Esta es una de las razones por las que siempre tiendo a escribir const
a la derecha del tipo y nunca al principio.