const char * y char const *: ¿son iguales?


81

Según tengo entendido, los constmodificadores deben leerse de derecha a izquierda. De eso, lo entiendo:

const char*

es un puntero cuyos elementos char no se pueden modificar, pero el puntero en sí sí puede, y

char const*

es un puntero constante a los mutablecaracteres.

Pero obtengo los siguientes errores para el siguiente código:

const char* x = new char[20];
x = new char[30];   //this works, as expected
x[0] = 'a';         //gives an error as expected

char const* y = new char[20];
y = new char[20];   //this works, although the pointer should be const (right?)
y[0] = 'a';         //this doesn't although I expect it to work

Entonces ... ¿cuál es? ¿Mi comprensión o mi compilador (VS 2005) son incorrectos?


35
En caso de duda, utilice siempre la regla de la espiral .
Alok Save

"... cuyos elementos char se pueden modificar, pero el puntero sí puede, y ..." - Creo que querías decir "no puedo" para una de esas "latas", pero no sé cómo confundido estás, así que no sé cuál corregir: P
detly

1
Pruebe este sitio web: www.cdecl.org
yasouser

El compilador nunca se equivoca;)
monolith

Respuestas:


129

En realidad, según el estándar, constmodifica el elemento directamente a su izquierda . El uso de constal comienzo de una declaración es solo un atajo mental conveniente. Entonces, las siguientes dos declaraciones son equivalentes:

char const * pointerToConstantContent1;
const char * pointerToConstantContent2;

Para asegurarse de que el puntero en sí no se modifique, constdebe colocarse después del asterisco:

char * const constantPointerToMutableContent;

Para proteger tanto el puntero como el contenido al que apunta, utilice dos consts.

char const * const constantPointerToConstantContent;

Personalmente, he adoptado siempre poner la constante después de la parte que no pretendo modificar para mantener la coherencia incluso cuando el puntero es la parte que deseo mantener constante.


23
'taquigrafía conveniente' es una descripción interesante para algo que no es más corto y no sigue las reglas normales.
beetstra

Al estándar realmente no le importa qué orden uses. La sección 7.1.6 solo muestra ambos lugares y dice que lo use solo en uno.
edA-qa mort-ora-y

1
@beetstra estoy de acuerdo. Lo cambié a "atajo mental conveniente" para ser un poco más claro.
Greyson

31

Funciona porque ambos son iguales. Puede que estés confundido en esto

const char*  // both are same
char const*

y

char* const  // unmutable pointer to "char"

y

const char* const  // unmutable pointer to "const char"

[Para recordar esto, aquí hay una regla simple, '*' afecta primero a todo su LHS ]


Ok, lo tengo ahora. Muchas gracias.
Luchian Grigore

1
unmutable pointer to char*.Es un puntero inmutable que apunta a charno char *.
Alok Save

25

Eso es porque la regla es:

REGLA: se constune a la izquierda, a menos que no haya nada a la izquierda, entonces se une a la derecha :)

entonces, mira estos como:

(const --->> char)*
(char <<--- const)*

ambos iguales! ah, y --->>y <<---NO son operadores, que acaba de mostrar lo que los constune a.


2
sí, el operador correcto es -->>y opera solo con valores. Prueba int i = 8; std::cout << (i -->> 1) << std::endl;:)
Alexander Malakhov

11

(de 2 pregunta de inicialización de variable simple )

Una muy buena regla general con respecto a const:

Leer declaraciones de derecha a izquierda.

(ver Vandevoorde / Josutiss "Plantillas C ++: La guía completa")

P.ej:

int const x; // x is a constant int
const int x; // x is an int which is const

// easy. the rule becomes really useful in the following:
int const * const p; // p is const-pointer to const-int
int const &p;        // p is a reference to const-int
int * const * p;     // p is a pointer to const-pointer to int.

Desde que sigo esta regla empírica, nunca volví a interpretar mal tales declaraciones.

(: sisab retcarahc-rep a no ton, sisab nekot-rep a no tfel-ot-thgir naem I hguohT: tidE


+1 ¡Esto es fantástico, gracias! He estado tratando de entender cosas como const char* constdurante años y gracias a ti ahora lo entiendo.
OMGtechy

5

Así es como siempre trato de interpretar:

char *p

     |_____ start from the asterisk. The above declaration is read as: "content of `p` is a `char`".

char * const p

     |_____ again start from the asterisk. "content of constant (since we have the `const` 
            modifier in the front) `p` is a `char`".

char const *p

           |_____ again start from the asterisk. "content of `p` is a constant `char`".

¡Espero eso ayude!


0

En ambos casos, estás apuntando a un carácter constante.

const char * x  //(1) a variable pointer to a constant char
char const * x  //(2) a variable pointer to a constant char
char * const x  //(3) a constant pointer to a variable char
char const * const x //(4) a constant pointer to a constant char
char const * const * x //(5) a variable pointer to a constant pointer to a constant char
char const * const * const x //(6) can you guess this one?

Por defecto, se constaplica a lo que está inmediatamente a la izquierda, pero podría aplicarse a lo que está inmediatamente a su derecha si no hay nada que lo preceda, como en (1).


Último: un puntero de variable constante, a un puntero constante, a un carácter constante.
Secko

Si por "puntero de variable constante" te refieres a "puntero constante", ¡lo has clavado hermano!
Lino Mediavilla

Bueno, en (5) ese es un puntero variable a un puntero constante a un carácter constante simplemente porque no hay "const" a la derecha del último asterisco antes del identificador "x". Pero en (6) eso se convierte en un puntero constante, el resto permanece igual.
Lino Mediavilla
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.