sirve que para c++ c pointers int const

c++ - que - const int arduino



¿Cuál es la diferencia entre const int*, const int*const y int const*? (14)

Siempre arruino la forma de usar const int* , const int * const y int const * correctamente. ¿Hay un conjunto de reglas que definen lo que puedes y no puedes hacer?

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


  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 en tamaño que el valor real, pero hay un efecto secundario y es porque es como un alias de la variable real. Podemos cambiar 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, entonces 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 que señala se conoce como un 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 y tampoco 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


Como casi todo el mundo señaló:

¿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 const": el objeto X no se puede cambiar a través de p.

  • X* const p significa "p es un puntero de const 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 de const a una X que es const": no se puede cambiar el puntero p, ni se puede cambiar el objeto X a través de p.


Creo que todo está respondido aquí ya, pero solo quiero agregar que debes tener cuidado con los typedef 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 poner const a la derecha del tipo, y nunca al principio.


Es simple pero complicado. Tenga en cuenta que podemos intercambiar el calificador const con cualquier tipo de datos ( int , char , float , etc.).

Veamos los siguientes ejemplos.

const int *p ==> *p es de solo lectura [ p es un puntero a un entero constante]

int const *p ==> *p es de solo lectura [ p es un puntero a un entero constante]

int *p const ==> Declaración errónea . El compilador lanza un error de sintaxis.

int *const p ==> p es de solo lectura [ p es un puntero constante a un entero]. Como el puntero p es de solo lectura, la declaración y la definición deben estar en el mismo lugar.

const int *p const ==> Declaración errónea . El compilador lanza un error de sintaxis.

const int const *p ==> *p es de solo lectura

const int *const p1 ==> *p y p son de solo lectura [ p es un puntero constante a un entero constante]. Como el puntero p es de solo lectura, la declaración y la definición deben estar en el mismo lugar.

int const *p const ==> Declaración errónea . El compilador lanza un error de sintaxis.

int const int *p ==> Declaración errónea . El compilador lanza un error de sintaxis.

int const const *p ==> *p es de solo lectura y es equivalente a int const *p

int const *const p ==> *p y p son de solo lectura [ p es un puntero constante a un entero constante]. Como el puntero p es de solo lectura, la declaración y la definición deben estar en el mismo lugar.


Esta pregunta muestra precisamente por qué me gusta hacer las cosas de la manera que mencioné en mi pregunta: ¿ se acepta const después de que sea id tipo?

En resumen, la forma más fácil de recordar la regla es que la "const" va después de lo que se aplica. En su pregunta, "int const *" significa que int es constante, mientras que "int * const" significa que el puntero es constante.

Si alguien decide ponerlo en el frente (por ejemplo: "const int *"), como excepción especial, en ese caso, se aplica a la cosa que está detrás de él.

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.


Esto aborda principalmente la segunda línea: mejores prácticas, asignaciones, parámetros de función, etc.

Práctica general. Intenta hacer todo lo que puedas. O para decirlo de otra manera, haga que todo comience con, y luego elimine exactamente el conjunto mínimo de const s necesario para permitir que el programa funcione. Esto será de gran ayuda para lograr la corrección constante y ayudará a garantizar que los errores sutiles no se presenten cuando las personas intenten y asignen cosas que no deben modificar.

Evita const_cast <> como la plaga. Hay uno o dos casos de uso legítimos para ello, pero son muy pocos y distantes entre sí. Si está tratando de cambiar un objeto const , lo hará mucho mejor para encontrar quien lo declaró const en el primer paso y hablará sobre el asunto con ellos para llegar a un consenso sobre lo que debería suceder.

Lo que lleva muy bien en las tareas. Puede asignarse a algo solo si no es constante. Si desea asignar en algo que es const, ver más arriba. Recuerda que en las declaraciones int const *foo; e int * const bar; hay diferentes cosas const ; otras respuestas aquí han cubierto ese tema admirablemente, así que no voy a entrar en ello.

Parámetros de la función:

Pase por valor: por ejemplo, void func(int param) no le importa de una manera u otra en el sitio de llamada. Se puede argumentar que existen casos de uso para declarar la función como void func(int const param) pero que no tiene efecto en el llamador, solo en la función en sí, ya que cualquier valor que se pase no puede ser cambiado por la función durante la llamada.

Pase por referencia: por ejemplo, void func(int &param) Ahora sí hay una diferencia. Como se acaba de declarar, la func tiene permitido cambiar param , y cualquier sitio de llamada debe estar listo para enfrentar las consecuencias. Cambiar la declaración a void func(int const &param) cambia el contrato, y garantiza que func ahora no puede cambiar param , lo que significa que lo que se pasa es lo que volverá a salir. Como han señalado otros, esto es muy útil para pasar de forma barata un objeto grande que no desea cambiar. Pasar una referencia es mucho más barato que pasar un objeto grande por valor.

Pase por el puntero: por ejemplo, void func(int *param) y void func(int const *param) Estos dos son prácticamente sinónimos de sus equivalentes de referencia, con la advertencia de que la función llamada ahora necesita verificar nullptr menos que nullptr alguna otra garantía contractual. asegura la func que nunca recibirá un nullptr en param .

Artículo de opinión sobre ese tema. Demostrar la corrección en un caso como este es terriblemente difícil, es demasiado fácil cometer un error. Así que no se arriesgue, y siempre verifique los parámetros del puntero para nullptr . Te ahorrarás dolor y sufrimiento y será difícil encontrar errores a largo plazo. Y en cuanto al costo del cheque, es muy barato, y en los casos donde el análisis estático incorporado en el compilador puede administrarlo, el optimizador lo eliminará de todos modos. Active la Generación de código de tiempo de enlace para MSVC o WOPR (creo) para GCC, y obtendrá todo el programa, es decir, incluso en llamadas a funciones que cruzan el límite de un módulo de código fuente.

Al final del día, todo lo anterior constituye un caso muy sólido para preferir siempre las referencias a los punteros. Son más seguros en todo momento.


Hay muchos otros puntos sutiles que rodean la corrección constante en C ++. Supongo que la pregunta aquí ha sido simplemente sobre C, pero daré algunos ejemplos relacionados ya que la etiqueta es C ++:

  • A menudo se pasan grandes argumentos como cadenas como TYPE const & que impiden que el objeto sea modificado o copiado. Ejemplo:

    TYPE& TYPE::operator=(const TYPE &rhs) { ... return *this; }

    Pero TYPE & const tiene sentido porque las referencias son siempre const.

  • Siempre debe etiquetar los métodos de clase que no modifican la clase como const , de lo contrario no puede llamar al método desde una TYPE const & reference. Ejemplo:

    bool TYPE::operator==(const TYPE &rhs) const { ... }

  • Hay situaciones comunes en las que tanto el valor de retorno como el método deben ser const. Ejemplo:

    const TYPE TYPE::operator+(const TYPE &rhs) const { ... }

    De hecho, los métodos const no deben devolver datos de clase internos como una referencia a no const.

  • Como resultado, a menudo se debe crear tanto un método const como un método non-const utilizando la sobrecarga const. Por ejemplo, si define T const& operator[] (unsigned i) const; , entonces probablemente también querrás la versión no constante dada por:

    inline T& operator[] (unsigned i) { return const_cast<char&>( static_cast<const TYPE&>(*this)[](i) ); }

Afaik, no hay funciones const en C, las funciones que no son miembros no pueden ser const en C ++, los métodos const pueden tener efectos secundarios y el compilador no puede usar las funciones const para evitar llamadas a funciones duplicadas. De hecho, incluso un simple int const & reference podría ser testigo de que el valor al que se refiere se cambie en otra parte.


Léalo al revés (según lo indicado por Clockwise / Spiral Rule ):

  • int* - puntero a int
  • int const * - puntero a const int
  • int * const - const point to int
  • int const * const - const puntero a const int

Ahora la primera const puede estar en cualquier lado del tipo, así 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 constante a un puntero a un int
  • int * const * - un puntero a un const puntero a un int
  • int const ** - un puntero a un puntero a un 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

const int* foo; int *const bar; //note, you actually need to set the pointer //here because you can''t change it later ;)

foo es un puntero variable a un entero constante. Esto le permite cambiar lo que apunta pero no el valor al 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 a qué cadena apunta pero no puede cambiar el contenido de estas cadenas. Esto es importante cuando la 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, normalmente usaría una referencia donde usaría un puntero T* const menos que necesite permitir punteros NULL .


La constante con la int en ambos lados hará que el puntero a constante int .

const int *ptr=&i;

o

int const *ptr=&i;

const después de ''*'' hará un puntero constante a int .

int *const ptr=&i;

En este caso, todos estos son punteros a un entero constante , pero ninguno de estos son punteros constantes.

const int *ptr1=&i, *ptr2=&j;

En este caso, todos son punteros a un entero constante y ptr2 es un puntero constante a un entero constante . Pero ptr1 no es puntero constante.

int const *ptr1=&i, *const ptr2=&j;


La regla general es que la palabra clave const aplica a lo que la precede inmediatamente. Excepción, una const partida se aplica a lo que sigue.

  • const int* es lo mismo que int const* y significa "puntero a constante int" .
  • const int* const es lo mismo que int const* const y significa "puntero constante a constante int" .

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


La sintaxis de declaración de C y C ++ ha sido descrita repetidamente como un experimento fallido, por los diseñadores originales.

En su lugar, vamos a nombrar el tipo "puntero a Type "; Lo llamaré Ptr_ :

template< class Type > using Ptr_ = Type*;

Ahora Ptr_<char> es un puntero a char .

Ptr_<const char> es un puntero a const char .

Y const Ptr_<const char> es un puntero de const char para const char .

Ahí.


Para aquellos que no conocen la Regla de las agujas del reloj / espiral: Comience desde el nombre de la variable, muévase hacia la derecha (en este caso, retroceda) al siguiente puntero o tipo . Repita hasta que la expresión termine.

Aquí hay una demo:


Tenía la misma duda que tú hasta que encontré este book del C ++ Guru Scott Meyers. Refiera el tercer artículo en este libro donde habla en detalles sobre el uso de const .

Solo sigue este consejo

  1. Si la palabra const aparece a la izquierda del asterisco, lo que apunta es constante
  2. Si la palabra const aparece a la derecha del asterisco, el puntero es constante
  3. Si aparece const en ambos lados, ambos son constantes.

Uso simple de ''const''

El uso más simple es declarar una constante nombrada. Para hacer esto, uno declara una constante como si fuera una variable pero agrega ''const'' antes de ella. Uno tiene que inicializarlo inmediatamente en el constructor porque, por supuesto, uno no puede establecer el valor más adelante, ya que eso lo alteraría. Por ejemplo,

const int Constant1=96;

creará una constante entera, unimaginativamente llamada ''Constant1'', con el valor 96.

Estas constantes son útiles para los parámetros que se utilizan en el programa, pero no es necesario cambiarlos después de compilar el programa. Tiene una ventaja para los programadores sobre el comando ''#define'' del preprocesador en que es comprendido y usado por el compilador, no solo sustituido por el preprocesador en el texto del programa antes de llegar al compilador principal, así que los mensajes de error son mucho más útiles .

También funciona con punteros, pero uno tiene que tener cuidado donde "const" para determinar si el puntero o lo que apunta es constante o ambos. Por ejemplo,

const int * Constant2

declara que Constant2 es un puntero variable a un entero constante y

int const * Constant2

Es una sintaxis alternativa que hace lo mismo, mientras que

int * const Constant3

declara que Constant3 es un puntero constante a un entero variable y

int const * const Constant4

declara que Constant4 es un puntero constante a un entero constante. Básicamente, ''const'' se aplica a lo que está a su izquierda inmediata (excepto si no hay nada en ese caso, se aplica a lo que está a su derecha inmediata).

ref: http://duramecho.com/ComputerInformation/WhyHowCppConst.html