Lo primero a la izquierda de la "constante" es lo que es constante. Si "const" es lo que está más alejado a la izquierda, entonces lo primero a la derecha es lo que es constante.
Cupcake
44
Como consejo amigable, nunca olvides que cdecl es una cosa.
Braden Best
Hay otro char const * que es el tipo de excepción de retorno :: what ()
Zhang
Respuestas:
363
La diferencia es que const char *es un puntero a a const char, mientras que char * constes un puntero constante a a char.
El primero, el valor al que se apunta no se puede cambiar, pero se puede cambiar el puntero. El segundo, el valor que se apunta puede cambiar pero el puntero no puede (similar a una referencia).
También hay una
constchar*const
que es un puntero constante a un carácter constante (por lo que no se puede cambiar nada al respecto).
Nota:
Las siguientes dos formas son equivalentes:
constchar*
y
charconst*
La razón exacta de esto se describe en el estándar C ++, pero es importante tener en cuenta y evitar la confusión. Conozco varios estándares de codificación que prefieren:
charconst
encima
constchar
(con o sin puntero) para que la ubicación del constelemento sea la misma que con un puntero const.
¿Valdría la pena observar lo que sucede si se especifican múltiples variables en la misma declaración? Creo const int *foo,*bar;que declararía ambos fooy barser int const *, pero int const *foo, *bardeclararía fooser int const *y barser int *. Creo typedef int * intptr; const intptr foo,bar;que declararía que ambas variables son int * const; No conozco ninguna forma de usar una declaración combinada para crear dos variables de ese tipo sin un typedef.
supercat
1
@supercat I believe const int *foo,*bar; would declare both foo and bar to be int const *: sí. but int const *foo, *bar would declare foo to be a int const * and bar to be int *: No! Sería exactamente lo mismo que el caso anterior. (Consulte ideone.com/RsaB7n donde obtiene el mismo error para foo y bar). I think typedef int * intptr; const intptr foo,bar; would declare both variables to be int * const: Si. I don't know any way to use a combined declaration to create two variables of that type without a typedef: Bueno, int *const foo, *const bar;. Sintaxis del
declarante
@gx_: Entonces me equivoqué, mi incertidumbre fue la razón por la que sugerí que podría ser útil decir cuáles son las reglas. ¿Qué haría int const *foo, *volatile barpara bar? Hazlo ambos consty volatile? Echo de menos la separación limpia de Pascal de los nombres de variables declaradas y sus tipos (sería un puntero a una matriz de punteros a enteros var foo: ^Array[3..4] of ^Integer; `` Creo que sería un paréntesis anidado divertido en C, creo.
supercat
3
@supercat (oh, solo C, perdón por el enlace del código C ++, llegué aquí por una pregunta C ++) Se trata de la sintaxis de la declaración C , con una parte de tipo ("puro") seguida de un declarador . En " int const *foo, *volatile bar" la parte tipo es int const(se detiene antes de *) y los declaradores son *foo(la expresión *foodenotará un int const) y *volatile bar; leer de derecha a izquierda (buena regla para los calificadores cv ), fooes un puntero a const int, y bares un puntero volátil a const int (el puntero en sí es volátil, el int puntiagudo es [accedido como] const).
gx_
@supercat Y en cuanto a "un puntero a un array de punteros a enteros" (no sé Pascal, no está seguro acerca de la [3..4]sintaxis, así que vamos a tomar una serie de 10 elementos): int *(*foo)[10];. Refleja su uso (futuro) como una expresión: *(*foo)[i](con iun número entero en el rango, [0, 10)es decir [0, 9]) primero desreferenciará foopara llegar a la matriz, luego accederá al elemento en el índice i(porque postfix se []une más fuerte que el prefijo *), luego desreferenciará este elemento, finalmente produciendo un int(ver ideone.com/jgjIjR ). Pero lo typedefhace más fácil (ver ideone.com/O3wb7d ).
gx_
102
Para evitar confusiones, siempre agregue el calificador const.
¿Por qué? "Para evitar la confusión" no explica cuál es la confusión para mí.
Andrew Weir el
14
@ Andrew: Estaba insinuando la consistencia y, por lo tanto, la legibilidad. Escribir todos los calificadores de tipo para que modifiquen lo que está a su izquierda, siempre , es lo que uso.
diapir
1
En realidad, es la mejor respuesta sobre el tema que he encontrado en SO
Trap
8
Como código estándar, rara vez he encontrado este estilo y, por lo tanto, no es probable que lo adopte. Sin embargo, como herramienta de aprendizaje, esta respuesta fue muy útil. (Así que supongo que lástima que este no sea un estilo más común.)
natevw
8
@Alla: pno se relaciona con el tipo: (const int *const). Para bien o para mal (peor si me preguntas) el calificador const, tanto en C como en C ++, debe ser postfix: cf función miembro const void foo(int a) const;. La posibilidad de declarar const intes la excepción más que la regla.
diapir
44
const siempre modifica lo que viene antes (a la izquierda), EXCEPTO cuando es lo primero en una declaración de tipo, donde modifica lo que viene después (a la derecha).
Entonces estos dos son iguales:
intconst*i1;constint*i2;
definen punteros a a const int. Puede cambiar dónde i1y i2puntos, pero no puede cambiar el valor al que apuntan.
Esta:
int*const i3 =(int*)0x12345678;
define un constpuntero a un entero y lo inicializa para apuntar a la ubicación de memoria 12345678. Puede cambiar el intvalor en la dirección 12345678, pero no puede cambiar la dirección a la que i3apunta.
const * chares un código C no válido y no tiene sentido. ¿Quizás quiso preguntar la diferencia entre a const char *y a char const *, o posiblemente la diferencia entre a const char *y a char * const?
const char*es un puntero a un caracter constante char* constes un puntero constante a un caracter const char* constes un puntero constante a un caracter constante
Regla de oro: ¡ lea la definición de derecha a izquierda!
const int *foo;
Significa " foopuntos ( *) a un intque no puede cambiar ( const)".
Para el programador esto significa "no cambiaré el valor de lo que fooapunta".
*foo = 123;o foo[0] = 123;sería inválido
foo = &bar; esta permitido.
int *const foo;
Significa " foono puede cambiar ( const) y puntos ( *) a int".
Para el programador esto significa "No cambiaré la dirección de memoria que se foorefiere".
*foo = 123;o foo[0] = 123;está permitido.
foo = &bar; Sería inválido.
const int *const foo;
Significa " foono puede cambiar ( const) y apunta ( *) a un intque no puede cambiar ( const)".
Para el programador esto significa "no cambiaré el valor de lo que fooapunta, ni cambiaré la dirección a la que se foorefiere".
const char * x Aquí X es básicamente un puntero de caracteres que apunta a un valor constante
char * const x se refiere al puntero de caracteres que es constante, pero la ubicación a la que apunta puede cambiar.
const char * const x es una combinación de 1 y 2, significa que es un puntero de caracteres constante que apunta a un valor constante.
const * char x causará un error del compilador. No se puede declarar.
char const * x es igual al punto 1.
la regla general es que si const tiene el nombre var, entonces el puntero será constante pero la ubicación de apuntado se puede cambiar ; de lo contrario, el puntero apuntará a una ubicación constante y el puntero puede apuntar a otra ubicación, pero el contenido de la ubicación de apuntado no se puede cambiar .
"char * const x se refiere al puntero de caracteres que es constante, pero la ubicación a la que apunta se puede cambiar". Incorrecto. El valor en la ubicación se puede cambiar, no la ubicación en sí.
favor
3
El primero es un error de sintaxis. Tal vez quisiste decir la diferencia entre
constchar* mychar
y
char*const mychar
En ese caso, el primero es un puntero a datos que no pueden cambiar, y el segundo es un puntero que siempre apuntará a la misma dirección.
Muchas respuestas proporcionan técnicas específicas, reglas generales, etc. para comprender esta instancia particular de declaración de variables. Pero hay una técnica genérica para entender cualquier declaración:
Según la regla en sentido horario / espiral, el apuntero al carácter es constante. Lo que significa que el carácter es constante pero el puntero puede cambiar. a = "other string";es decir, está bien pero a[2] = 'c';no se compilará
SI)
char*const a;
Según la regla, aes un puntero constante a un personaje. es decir, puedes hacer a[2] = 'c';pero no puedes hacera = "other string";
(Sería mucho mejor si la esencia de la respuesta no estuviera oculta detrás de un enlace, con el texto aquí ni siquiera citando, o al menos refiriéndose, a ninguno de sus detalles, más allá de un genérico "según la regla")
Sz.
@Sz. ¿Tienes alguna confusión específica aquí que pueda aclarar? Realmente no hay mucho después de conocer la regla.
PnotNP
1
Supongo que te refieres a const char * y char * const.
El primero, const char *, es un puntero a un carácter constante. El puntero en sí mismo es mutable.
El segundo, char * const es un puntero constante a un personaje. El puntero no puede cambiar, el personaje al que apunta puede.
Y luego está const char * const donde el puntero y el carácter no pueden cambiar.
Su dos primeros son en realidad la misma y su tercero es un error del compilador :)
workmad3
1
Aquí hay una explicación detallada con código
/*const char * p;
char * const p;
const char * const p;*/// these are the three conditions,// const char *p;const char * const p; pointer value cannot be changed// char * const p; pointer address cannot be changed// const char * const p; both cannot be changed.#include<stdio.h>/*int main()
{
const char * p; // value cannot be changed
char z;
//*p = 'c'; // this will not work
p = &z;
printf(" %c\n",*p);
return 0;
}*//*int main()
{
char * const p; // address cannot be changed
char z;
*p = 'c';
//p = &z; // this will not work
printf(" %c\n",*p);
return 0;
}*//*int main()
{
const char * const p; // both address and value cannot be changed
char z;
*p = 'c'; // this will not work
p = &z; // this will not work
printf(" %c\n",*p);
return 0;
}*/
// Some more complex constant variable/pointer declaration.// Observing cases when we get error and warning would help// understanding it better.int main(void){char ca1[10]="aaaa";// char array 1char ca2[10]="bbbb";// char array 2char*pca1= ca1;char*pca2= ca2;charconst*ccs= pca1;char*const csc= pca2;
ccs[1]='m';// Bad - error: assignment of read-only location ‘*(ccs + 1u)’
ccs= csc;// Good
csc[1]='n';// Good
csc= ccs;// Bad - error: assignment of read-only variable ‘csc’charconst**ccss=&ccs;// Goodcharconst**ccss1=&csc;// Bad - warning: initialization from incompatible pointer typechar*const*cscs=&csc;// Goodchar*const*cscs1=&ccs;// Bad - warning: initialization from incompatible pointer typechar**const cssc=&pca1;// Goodchar**const cssc1=&ccs;// Bad - warning: initialization from incompatible pointer typechar**const cssc2=&csc;// Bad - warning: initialization discards ‘const’// qualifier from pointer target type*ccss[1]='x';// Bad - error: assignment of read-only location ‘**(ccss + 8u)’*ccss= ccs;// Good*ccss= csc;// Good
ccss= ccss1;// Good
ccss= cscs;// Bad - warning: assignment from incompatible pointer type*cscs[1]='y';// Good*cscs= ccs;// Bad - error: assignment of read-only location ‘*cscs’*cscs= csc;// Bad - error: assignment of read-only location ‘*cscs’
cscs= cscs1;// Good
cscs= cssc;// Good*cssc[1]='z';// Good*cssc= ccs;// Bad - warning: assignment discards ‘const’// qualifier from pointer target type*cssc= csc;// Good*cssc= pca2;// Good
cssc= ccss;// Bad - error: assignment of read-only variable ‘cssc’
cssc= cscs;// Bad - error: assignment of read-only variable ‘cssc’
cssc= cssc1;// Bad - error: assignment of read-only variable ‘cssc’}
Puntero constante : un puntero constante puede apuntar solo a una sola variable del tipo de datos respectivo durante todo el programa. Podemos cambiar el valor de la variable apuntada por el puntero. La inicialización debe hacerse durante el tiempo de la declaración misma.
Sintaxis:
datatype *const var;
char *const viene bajo este caso.
/*program to illustrate the behaviour of constant pointer */#include<stdio.h>int main(){int a=10;int*const ptr=&a;*ptr=100;/* we can change the value of object but we cannot point it to another variable.suppose another variable int b=20; and ptr=&b; gives you error*/
printf("%d",*ptr);return0;}
Puntero a un valor constante : en este, un puntero puede apuntar cualquier número de variables del tipo respectivo, pero no podemos cambiar el valor del objeto señalado por el puntero en ese momento específico.
Sintaxis:
const datatype *varo datatype const *var
const char* viene bajo este caso.
/* program to illustrate the behavior of pointer to a constant*/#include<stdio.h>int main(){int a=10,b=20;intconst*ptr=&a;
printf("%d\n",*ptr);/* *ptr=100 is not possible i.e we cannot change the value of the object pointed by the pointer*/
ptr=&b;
printf("%d",*ptr);/*we can point it to another object*/return0;}
El constmodificador se aplica al término inmediatamente a su izquierda. La única excepción a esto es cuando no hay nada a su izquierda, entonces se aplica a lo que está inmediatamente a su derecha.
Estas son todas formas equivalentes de decir "puntero constante a una constante char":
¿Es dependiente del compilador? gcc produce para "const char const *" y "const const char *" y "char const const *" el mismo resultado -> el puntero podría apuntar a otra ubicación.
cosinus0
1
Dos reglas
If const is between char and *, it will affect the left one.
If const is not between char and *, it will affect the nearest one.
p.ej
char const *. This is a pointer points to a constant char.
char * const. This is a constant pointer points to a char.
Me gustaría señalar que usar int const *(o const int *) no se trata de un puntero que apunta a una const intvariable, sino que esta variable es constpara este puntero específico.
Por ejemplo:
int var =10;intconst* _p =&var;
El código anterior se compila perfectamente bien. _papunta a una constvariable, aunque en varsí misma no es constante.
Respuestas:
La diferencia es que
const char *es un puntero a aconst char, mientras quechar * constes un puntero constante a achar.El primero, el valor al que se apunta no se puede cambiar, pero se puede cambiar el puntero. El segundo, el valor que se apunta puede cambiar pero el puntero no puede (similar a una referencia).
También hay una
que es un puntero constante a un carácter constante (por lo que no se puede cambiar nada al respecto).
Nota:
Las siguientes dos formas son equivalentes:
y
La razón exacta de esto se describe en el estándar C ++, pero es importante tener en cuenta y evitar la confusión. Conozco varios estándares de codificación que prefieren:
encima
(con o sin puntero) para que la ubicación del
constelemento sea la misma que con un punteroconst.fuente
const int *foo,*bar;que declararía ambosfooybarserint const *, peroint const *foo, *bardeclararíafooserint const *ybarserint *. Creotypedef int * intptr; const intptr foo,bar;que declararía que ambas variables sonint * const; No conozco ninguna forma de usar una declaración combinada para crear dos variables de ese tipo sin un typedef.I believe const int *foo,*bar; would declare both foo and bar to be int const *: sí.but int const *foo, *bar would declare foo to be a int const * and bar to be int *: No! Sería exactamente lo mismo que el caso anterior. (Consulte ideone.com/RsaB7n donde obtiene el mismo error para foo y bar).I think typedef int * intptr; const intptr foo,bar; would declare both variables to be int * const: Si.I don't know any way to use a combined declaration to create two variables of that type without a typedef: Bueno,int *const foo, *const bar;. Sintaxis delint const *foo, *volatile barparabar? Hazlo ambosconstyvolatile? Echo de menos la separación limpia de Pascal de los nombres de variables declaradas y sus tipos (sería un puntero a una matriz de punteros a enterosvar foo: ^Array[3..4] of ^Integer; `` Creo que sería un paréntesis anidado divertido en C, creo.int const *foo, *volatile bar" la parte tipo esint const(se detiene antes de*) y los declaradores son*foo(la expresión*foodenotará unint const) y*volatile bar; leer de derecha a izquierda (buena regla para los calificadores cv ),fooes un puntero a const int, ybares un puntero volátil a const int (el puntero en sí es volátil, el int puntiagudo es [accedido como] const).[3..4]sintaxis, así que vamos a tomar una serie de 10 elementos):int *(*foo)[10];. Refleja su uso (futuro) como una expresión:*(*foo)[i](coniun número entero en el rango,[0, 10)es decir[0, 9]) primero desreferenciaráfoopara llegar a la matriz, luego accederá al elemento en el índicei(porque postfix se[]une más fuerte que el prefijo*), luego desreferenciará este elemento, finalmente produciendo unint(ver ideone.com/jgjIjR ). Pero lotypedefhace más fácil (ver ideone.com/O3wb7d ).Para evitar confusiones, siempre agregue el calificador const.
fuente
pno se relaciona con el tipo:(const int *const). Para bien o para mal (peor si me preguntas) el calificador const, tanto en C como en C ++, debe ser postfix: cf función miembro constvoid foo(int a) const;. La posibilidad de declararconst intes la excepción más que la regla.constsiempre modifica lo que viene antes (a la izquierda), EXCEPTO cuando es lo primero en una declaración de tipo, donde modifica lo que viene después (a la derecha).Entonces estos dos son iguales:
definen punteros a a
const int. Puede cambiar dóndei1yi2puntos, pero no puede cambiar el valor al que apuntan.Esta:
define un
constpuntero a un entero y lo inicializa para apuntar a la ubicación de memoria 12345678. Puede cambiar elintvalor en la dirección 12345678, pero no puede cambiar la dirección a la quei3apunta.fuente
const * chares un código C no válido y no tiene sentido. ¿Quizás quiso preguntar la diferencia entre aconst char *y achar const *, o posiblemente la diferencia entre aconst char *y achar * const?Ver también:
fuente
const char*es un puntero a un caracter constantechar* constes un puntero constante a un caracterconst char* constes un puntero constante a un caracter constantefuente
Regla de oro: ¡ lea la definición de derecha a izquierda!
const int *foo;Significa "
foopuntos (*) a unintque no puede cambiar (const)".Para el programador esto significa "no cambiaré el valor de lo que
fooapunta".*foo = 123;ofoo[0] = 123;sería inválidofoo = &bar;esta permitido.int *const foo;Significa "
foono puede cambiar (const) y puntos (*) aint".Para el programador esto significa "No cambiaré la dirección de memoria que se
foorefiere".*foo = 123;ofoo[0] = 123;está permitido.foo = &bar;Sería inválido.const int *const foo;Significa "
foono puede cambiar (const) y apunta (*) a unintque no puede cambiar (const)".Para el programador esto significa "no cambiaré el valor de lo que
fooapunta, ni cambiaré la dirección a la que sefoorefiere".*foo = 123;ofoo[0] = 123;sería inválidofoo = &bar;Sería inválido.fuente
const char * x Aquí X es básicamente un puntero de caracteres que apunta a un valor constante
char * const x se refiere al puntero de caracteres que es constante, pero la ubicación a la que apunta puede cambiar.
const char * const x es una combinación de 1 y 2, significa que es un puntero de caracteres constante que apunta a un valor constante.
const * char x causará un error del compilador. No se puede declarar.
char const * x es igual al punto 1.
la regla general es que si const tiene el nombre var, entonces el puntero será constante pero la ubicación de apuntado se puede cambiar ; de lo contrario, el puntero apuntará a una ubicación constante y el puntero puede apuntar a otra ubicación, pero el contenido de la ubicación de apuntado no se puede cambiar .
fuente
El primero es un error de sintaxis. Tal vez quisiste decir la diferencia entre
y
En ese caso, el primero es un puntero a datos que no pueden cambiar, y el segundo es un puntero que siempre apuntará a la misma dirección.
fuente
Otra regla general es verificar dónde está const :
fuente
Muchas respuestas proporcionan técnicas específicas, reglas generales, etc. para comprender esta instancia particular de declaración de variables. Pero hay una técnica genérica para entender cualquier declaración:
UNA)
Según la regla en sentido horario / espiral, el
apuntero al carácter es constante. Lo que significa que el carácter es constante pero el puntero puede cambiar.a = "other string";es decir, está bien peroa[2] = 'c';no se compilaráSI)
Según la regla,
aes un puntero constante a un personaje. es decir, puedes hacera[2] = 'c';pero no puedes hacera = "other string";fuente
Supongo que te refieres a const char * y char * const.
El primero, const char *, es un puntero a un carácter constante. El puntero en sí mismo es mutable.
El segundo, char * const es un puntero constante a un personaje. El puntero no puede cambiar, el personaje al que apunta puede.
Y luego está const char * const donde el puntero y el carácter no pueden cambiar.
fuente
Aquí hay una explicación detallada con código
fuente
fuente
Sintaxis:
char *constviene bajo este caso.Sintaxis:
const datatype *varodatatype const *varconst char*viene bajo este caso.fuente
char * const y const char *?
const char * p;// el valor no se puede cambiarchar * const p;// la dirección no se puede cambiarconst char * const p;// ambos no se pueden cambiar.fuente
El
constmodificador se aplica al término inmediatamente a su izquierda. La única excepción a esto es cuando no hay nada a su izquierda, entonces se aplica a lo que está inmediatamente a su derecha.Estas son todas formas equivalentes de decir "puntero constante a una constante
char":const char * constconst char const *char const * constchar const const *fuente
Dos reglas
If const is between char and *, it will affect the left one.If const is not between char and *, it will affect the nearest one.p.ej
char const *. This is a pointer points to a constant char.char * const. This is a constant pointer points to a char.fuente
Me gustaría señalar que usar
int const *(oconst int *) no se trata de un puntero que apunta a unaconst intvariable, sino que esta variable esconstpara este puntero específico.Por ejemplo:
El código anterior se compila perfectamente bien.
_papunta a unaconstvariable, aunque envarsí misma no es constante.fuente
Recuerdo del libro checo sobre C: lea la declaración de que comienza con la variable y vaya a la izquierda. Entonces para
puede leer como: "
aes una variable de tipo puntero constante achar",puede leer como: "
aes un puntero a una variable constante de tipo char. Espero que esto ayude.Prima:
Leerá como
aes un puntero constante a una variable constante de tipo char.fuente