¿Qué significa un puntero a puntero const en C y en C++?

4 minutos de lectura

avatar de usuario
Niklas

Conozco la regla empírica para leer las declaraciones de derecha a izquierda y estaba bastante seguro de que sabía lo que estaba pasando hasta que un colega me dijo que:

const MyStructure** ppMyStruct;

significa “ppMyStruct es un puntero a una const puntero a una MyStructure (mutable)” (en C++).

Hubiera pensado que significaba “ppMyStruct es un puntero a un puntero a una const MyStructure“. Busqué una respuesta en la especificación de C++, pero aparentemente no soy muy bueno en eso…

¿Qué significa en C++ y significa lo mismo en C?

Tu colega está equivocado. Es un puntero (no constante) a un puntero (no constante) a una MiEstructura constante. Tanto en C como en C++.

  • También es parte de la razón por la que a veces verá la ortografía alternativa recomendada: MyStructure const * *ppMyStruct; luego puede leer de derecha a izquierda: puntero a puntero a const Mystructure.

    – Joris Timmermans

    3 de diciembre de 2008 a las 14:00

  • ¿Quién lee RTL? Seguro que ninguno de mis clientes 🙂 Creo que no necesitamos soporte RTL, ¿verdad?

    – dom0

    27 de julio de 2013 a las 19:14

  • Esta es una publicación anterior, por lo que probablemente no se responda mi pregunta de comentario: ¿Cómo crear un puntero const a un puntero const a una MyStructure const?

    – chronis

    31 de enero de 2015 a las 15:22

  • @tchronis, no he probado (solo que compila), pero intente algo como: MyStructure const * const * const ptrMyStr;

    – Javier Sr.

    28 de abril de 2015 a las 7:01

En tales casos, la herramienta cdecl (o c++decl) puede ser útil:

     [flolo@titan ~]$ cdecl explain "const struct s** ppMyStruct"
     declare ppMyStruct as pointer to pointer to const struct s

  • Muy útil. ¿Por qué no es conocida esta herramienta?

    – David Holm

    3 de diciembre de 2008 a las 10:59

  • ¿Sabes si está disponible para Windows?

    – Niklas

    3 de diciembre de 2008 a las 11:03

  • Es de código abierto y, afaik, no tiene requisitos específicos para el sistema operativo. Cuando tenga suerte, debería ser compilable con cualquier compilador, en el peor de los casos, debe usar las cosas gcc/cygwin o mingw.

    – flolo

    3 de diciembre de 2008 a las 11:13

  • @flolo eres un héroe! ¡Nunca había oído hablar de esa herramienta! ¡Gracias por compartirlo! +1

    – DJJ

    6 de marzo de 2020 a las 3:01

  • Versión en línea en cdecl.org ¡También funciona al revés! Ingrese el inglés, obtenga el código.

    – Hormiga

    29 de junio de 2020 a las 10:21


Tenías razón en tu interpretación. Aquí hay otra forma de verlo:

const MyStructure *      *ppMyStruct;        // ptr --> ptr --> const MyStructure
      MyStructure *const *ppMyStruct;        // ptr --> const ptr --> MyStructure
      MyStructure *      *const ppMyStruct;  // const ptr --> ptr --> MyStructure

Estas son todas las alternativas de un puntero a puntero con un calificador const. La regla de derecha a izquierda se puede usar para descifrar las declaraciones (al menos en C++; no soy un experto en C).

  • ¿Qué pasa con MyStructure const* *ppMyStruct;?

    – Tobi

    19 de enero de 2013 a las 20:56

  • @tobi, eso es lo mismo que la primera línea. Consulte stackoverflow.com/q/3694630 (hablan de referencias, pero los punteros se comportan igual).

    – efotinis

    20 de enero de 2013 a las 15:35

avatar de usuario
csl

Su colega está equivocado y es lo mismo para C y C++. Prueba lo siguiente:

typedef struct foo_t {
    int i;
} foo_t;

int main()
{
    foo_t f = {123};
    const foo_t *p = &f;
    const foo_t **pp = &p;
    printf("f.i = %d\n", (*pp)->i);
    (*pp)->i = 888; // error
    p->i = 999;     // error
}

Visual C++ 2008 da los siguientes errores para las dos últimas líneas:

error C2166: l-value specifies const object
error C2166: l-value specifies const object

CCG 4 dice:

error: assignment of read-only location '**pp'
error: assignment of read-only location '*p'

g ++ 4 dice:

error: assignment of data-member 'foo_t::i' in read-only structure
error: assignment of data-member 'foo_t::i' in read-only structure

avatar de usuario
xtofl

tienen razón.

Otra respuesta ya apuntaba a la “Regla espiral en el sentido de las agujas del reloj“. Me gustó mucho ese, aunque un poco elaborado.

avatar de usuario
MSalters

Como corolario de los otros comentarios, no ponga ‘const’ primero. Realmente pertenece después del tipo. Eso habría aclarado el significado de inmediato, solo léalo RTL como de costumbre:

MyStructure const** ppMyStruct;

void Foo( int       *       ptr,
          int const *       ptrToConst,
          int       * const constPtr,
          int const * const constPtrToConst )
{
    *ptr = 0; // OK: modifies the pointee
    ptr  = 0; // OK: modifies the pointer

    *ptrToConst = 0; // Error! Cannot modify the pointee
    ptrToConst  = 0; // OK: modifies the pointer

    *constPtr = 0; // OK: modifies the pointee
    constPtr  = 0; // Error! Cannot modify the pointer

    *constPtrToConst = 0; // Error! Cannot modify the pointee
    constPtrToConst  = 0; // Error! Cannot modify the pointer
}

  • No veo cómo esto es una respuesta a la pregunta. ¿Lo leíste mal?

    – Niklas

    6 de febrero de 2010 a las 8:14

¿Ha sido útil esta solución?