¿Cuál es la diferencia entre const int*, const int * const e int const *?

11 minutos de lectura

Siempre me lío cómo usar const int*, const int * consty int const * correctamente. ¿Existe un conjunto de reglas que definan lo que puede y no puede hacer?

Quiero saber todo lo que se debe y no se debe hacer en términos de asignaciones, pasar a las funciones, etc.

  • Puedes usar el “Regla en el sentido de las agujas del reloj/espiral” para descifrar la mayoría de las declaraciones de C y C++.

    –James McNellis

    13 de junio de 2010 a las 20:49

  • cdecl.org es un gran sitio web que traduce automáticamente declaraciones C para usted.

    – Dave

    2 de noviembre de 2010 a las 19:37


  • @Calmarius: comience donde está/debe estar el nombre del tipo, muévase a la derecha cuando pueda, a la izquierda cuando deba. int *(*)(char const * const). Comience a la derecha del paréntesis * entonces tenemos que movernos a la izquierda: pointer. Fuera de los paréntesis, podemos movernos a la derecha: pointer to function of .... Luego tenemos que movernos a la izquierda: pointer to function of ... that returns pointer to int. Repita para expandir el parámetro (el ...): pointer to function of (constant pointer to constant char) that returns pointer to int. ¿Cuál sería la declaración equivalente de una línea en un lenguaje fácil de leer como Pascal?

    – Mark K. Cowan

    9 de julio de 2015 a las 17:08


  • @MarkKCowan En Pascal sería algo así como function(x:^char):^int. Hay tipos de funciones que implican un puntero a una función, por lo que no es necesario especificarlo, y Pascal no impone la corrección constante. Se puede leer de izquierda a derecha.

    – Calmarius

    9 de julio de 2015 a las 20:54


  • Lo primero a la izquierda de “const” es lo que es constante. Si “const” es lo que está más a la izquierda, entonces lo primero a la derecha es lo que es constante.

    – Magdalena

    31 de julio de 2016 a las 4:41

¿Cual es la diferencia entre const int const int
Precio mate

Léalo al revés (como impulsado por Regla en el sentido de las agujas del reloj/espiral):

  • int* – puntero a int
  • int const * – puntero a const int
  • int * const – const puntero a int
  • int const * const – const puntero a const int

ahora el primero const puede estar a ambos lados del tipo, por lo que:

  • 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 int
  • int ** const – un puntero const a un puntero a un int
  • int * const * – un puntero a una const puntero a un int
  • int const ** – un puntero a un puntero a una const int
  • int * const * const – un puntero const a un puntero const a un int

Y 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 entero constante. Esto le permite cambiar lo que apunta, pero no el valor que apunta. La mayoría de las veces, esto se ve con cadenas de estilo C donde tiene un puntero a un const char. Puede cambiar la cadena a la que apunta, pero no puede cambiar el contenido de estas cadenas. Esto es importante cuando la propia cadena 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, generalmente usaría una referencia donde usaría un T* const puntero a menos que necesite permitir NULL punteros

  • Me gustaría agregar una regla general que puede ayudarlo a recordar cómo descubrir si ‘const’ se aplica al puntero o a los datos señalados: divida la declaración en el signo de asterisco, luego, si la palabra clave const aparece en la parte izquierda (como en ‘const int * foo’) – pertenece a datos apuntados, si está en la parte derecha (‘int * const bar’) – se trata del puntero.

    – Miguel

    17 de julio de 2009 a las 17:26

  • @Michael: Felicitaciones a Michael por una regla tan simple para recordar/comprender la regla constante.

    – sivabudh

    11 de febrero de 2010 a las 19:00

  • @Jeffrey: leerlo al revés funciona bien siempre que no haya paréntesis. Pues… usar definiciones de tipo

    – Pato mugido

    28 mayo 2013 a las 19:53


  • +1, aunque un mejor resumen sería: leer declaraciones de puntero al revéseso significa, cerca de la declaración de @Michael: detener la lectura normal de izquierda a derecha en el primero asterisco.

    – Lobo

    18 de junio de 2014 a las 9:21


  • @gedamial lo hace, funciona bien, pero debe asignarlo al mismo tiempo que lo declara (porque no puede reasignar un “puntero constante”). const int x = 0; const int *const px = &x; const int *const *const p = &px; funciona bien

    – RastaJedi

    08/08/2016 a las 23:15

1647654490 108 ¿Cual es la diferencia entre const int const int
Shijing Nv

Para aquellos que no saben acerca de la regla de las agujas del reloj/espiral: Comience desde el nombre de la variable, muévase en el sentido de las agujas del reloj (en este caso, muévase hacia atrás) a la siguiente puntero o escribe. Repita hasta que termine la expresión.

Aquí hay una demostración:

puntero a int

const puntero a int const

puntero a const int

puntero a const int

const puntero a int

  • @Jan el enlace para el ejemplo complejo no tiene permisos. ¿Puedes publicarlo directamente aquí o eliminar las restricciones de visualización?

    – R71

    8 de abril de 2016 a las 12:03

  • @Rog solía tener todos los permisos de acceso abierto… Desafortunadamente, no escribí el artículo y no tengo permisos de acceso. Sin embargo, aquí hay una versión archivada del artículo que aún funciona: archivo.is/SsfMX

    – Jan Rüegg

    08/04/2016 a las 13:34

  • El ejemplo complejo sigue siendo de derecha a izquierda, pero incluye la resolución de paréntesis como se haría normalmente. Todo el asunto de la espiral en el sentido de las agujas del reloj no lo hace más fácil.

    – Mateo Lee

    18/09/2016 a las 23:04

  • Último ejemplo: void (*signal(int, void (*fp)(int)))(int); de archive.is/SsfMX

    – naXa

    3 mayo 2017 a las 19:04

  • No confíe en esta regla. Esto no es universal. Hay algunos casos en los que falla.

    – trucos

    12 de mayo de 2017 a las 7:17

¿Cual es la diferencia entre const int const int
Dragón Kaz

Creo que todo ya está respondido aquí, pero solo quiero agregar que debes tener cuidado con typedef¡s! NO son solo reemplazos de texto.

Por ejemplo:

typedef char *ASTRING;
const ASTRING astring;

El tipo de astring es char * constno const char *. Esta es una razón por la que siempre tiendo a poner const a la derecha del tipo, y nunca al principio.

  • Y para mí, esta es la razón por la que nunca tipeo los punteros def. No veo el beneficio en cosas como typedef int* PINT (Supongo que es algo que surgió de las prácticas en C y muchos desarrolladores siguieron haciéndolo). Genial, lo reemplacé * con un Pno acelera la escritura, además de presentar el problema que mencionas.

    – Mefane

    28 de enero de 2011 a las 13:01

  • @Mephane – Puedo ver eso. Sin embargo, me parece un poco al revés evitar una función de lenguaje agradable para seguir usando una regla sintáctica excepcional (sobre la ubicación de “const”), en lugar de evitar el uso de la regla sintáctica excepcional para que pueda usar esta función de lenguaje de manera segura. .

    – TED

    17 de octubre de 2012 a las 14:06


  • @Mephane PINT es de hecho un uso bastante tonto de un typedef, especialmente porque me hace pensar que las tiendas del sistema usan cerveza para la memoria. Sin embargo, typedef s son bastante útiles para tratar con punteros a funciones.

    – Acercándose a la OscuridadPez

    26 de diciembre de 2013 a las 21:07

  • @KazDragon ¡GRACIAS! Sin él, me habría equivocado con todos esos typedefed PVOID, LPTSTR cosas en Win32 api!

    –David Lee

    8 mayo 2014 a las 12:29


  • @Mephane: Tuve que usar pAlgo un par de veces cuando usaba ciertas macros heredadas que se escribieron para aceptar un tipo, pero se separarían si el tipo no fuera un único identificador alfanumérico. 🙂

    – Groo

    8 mayo 2017 a las 16:37

1647654492 693 ¿Cual es la diferencia entre const int const int
lucas

Como casi todos señalaron:

Cuál es la diferencia entre const X* p, X* const p y const X* const p?

Tienes que leer las declaraciones de puntero de derecha a izquierda.

  • const X* p significa “p apunta a una X que es constante”: el objeto X no se puede cambiar a través de p.

  • X* const p significa “p es un puntero constante a una X que no es constante”: no puede cambiar el puntero p en sí, pero puede cambiar el objeto X a través de p.

  • const X* const p significa “p es un puntero constante a una X que es constante”: no puede cambiar el puntero p en sí mismo, ni puede cambiar el objeto X a través de p.

¿Cual es la diferencia entre const int const int
Behrooz Tabesh

  1. Referencia constante:

    Una referencia a una variable (aquí int), que es constante. Pasamos la variable como referencia principalmente, porque las referencias son más pequeñas que el valor real, pero hay un efecto secundario y es que es como un alias de la variable real. Es posible que cambiemos accidentalmente la variable principal a través de nuestro acceso completo al alias, por lo que lo hacemos constante para evitar este efecto secundario.

    int var0 = 0;
    const int &ptr1 = var0;
    ptr1 = 8; // Error
    var0 = 6; // OK
    
  2. Punteros constantes

    Una vez que un puntero constante apunta a una variable, no puede apuntar a ninguna otra variable.

    int var1 = 1;
    int var2 = 0;
    
    int *const ptr2 = &var1;
    ptr2 = &var2; // Error
    
  3. Puntero a constante

    Un puntero a través del cual no se puede cambiar el valor de una variable a la que apunta se conoce como puntero a constante.

    int const * ptr3 = &var2;
    *ptr3 = 4; // Error
    
  4. Puntero constante a una constante

    Un puntero constante a una constante es un puntero que no puede cambiar la dirección a la que apunta ni puede cambiar el valor guardado en esa dirección.

    int var3 = 0;
    int var4 = 0;
    const int * const ptr4 = &var3;
    *ptr4 = 1;     // Error
     ptr4 = &var4; // Error
    

1647654493 127 ¿Cual es la diferencia entre const int const int
Azeem

La regla general es que el const palabra clave se aplica a lo que le precede inmediatamente. Excepción, un comienzo const se aplica a lo que sigue.

  • const int* es lo mismo que int const* y medios “puntero a int constante”.
  • const int* const es lo mismo que int const* const y medios “puntero constante a int constante”.

Editar:
Para lo que se debe y lo que no se debe hacer, si esta respuesta no es suficiente, ¿podría ser más preciso sobre lo que quiere?

1647654493 366 ¿Cual es la diferencia entre const int const int
Comunidad

Esta pregunta muestra precisamente ¿Por qué me gusta hacer las cosas de la manera que mencioné en mi pregunta es constante después de la identificación del tipo aceptable?

En resumen, creo que la forma más fácil de recordar la regla es que la “const” va después la cosa a la que se aplica. Entonces, en su pregunta, “int const *” significa que int es constante, mientras que “int * const” significaría que el puntero es constante.

Si alguien decide ponerlo al principio (p. ej.: “const int *”), como excepción especial en ese caso, se aplica a lo que sigue.

A muchas personas les gusta usar esa excepción especial porque piensan que se ve mejor. No me gusta, porque es una excepción, y por lo tanto confunde las cosas.

  • Estoy desgarrado en este tema. Lógicamente tiene sentido. Sin embargo, la mayoría de los desarrolladores de C++ escribirían const T* y se ha vuelto más natural. ¿Con qué frecuencia alguna vez usa un T* const de todos modos, por lo general una referencia funcionará bien. Me mordió todo esto una vez cuando quería un boost::shared_ptr<const T> y en su lugar escribió const boost::shared_ptr<T>. El mismo problema en un contexto ligeramente diferente.

    – Precio mate

    17 de julio de 2009 a las 14:08

  • En realidad, uso punteros constantes con más frecuencia que constantes. Además, debe pensar en cómo va a reaccionar en presencia de punteros a punteros (etc.). Es cierto que esos son más raros, pero sería bueno pensar en las cosas de una manera en la que pueda manejar estas situaciones con aplomo.

    – TED

    17 de julio de 2009 a las 14:19

  • La otra buena ventaja de colocar la const a la derecha del tipo es que ahora todo a la izquierda de cualquier const es el tipo de lo que es const, y todo a su derecha es lo que en realidad es const. Llevar int const * const * p; como ejemplo. No, normalmente no escribo así, esto es solo un ejemplo. Primero const: escriba int, y el int que es const es el contenido del puntero const que es el contenido de p. Segunda const: el tipo es un puntero a const int, const oblect es el contenido de p

    – dnuff

    15 de marzo de 2018 a las 7:18

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad