Cuál es la diferencia entre:
char * const
y
const char *
Cuál es la diferencia entre:
char * const
y
const char *
Respuestas:
La diferencia es que const char *
es un puntero a a const char
, mientras que char * const
es 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
const char * 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:
const char *
y
char const *
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:
char const
encima
const char
(con o sin puntero) para que la ubicación del const
elemento sea la misma que con un puntero const
.
const int *foo,*bar;
que declararía ambos foo
y bar
ser int const *
, pero int const *foo, *bar
declararía foo
ser int const *
y bar
ser 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.
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
int const *foo, *volatile bar
para bar
? Hazlo ambos const
y 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.
int const *foo, *volatile bar
" la parte tipo es int const
(se detiene antes de *
) y los declaradores son *foo
(la expresión *foo
denotará un int const
) y *volatile bar
; leer de derecha a izquierda (buena regla para los calificadores cv ), foo
es un puntero a const int, y bar
es 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]
(con i
un número entero en el rango, [0, 10)
es decir [0, 9]
) primero desreferenciará foo
para 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 typedef
hace más fácil (ver ideone.com/O3wb7d ).
Para evitar confusiones, siempre agregue el calificador const.
int * mutable_pointer_to_mutable_int;
int const * mutable_pointer_to_constant_int;
int *const constant_pointer_to_mutable_int;
int const *const constant_pointer_to_constant_int;
p
no 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 int
es la excepción más que la regla.
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:
int const *i1;
const int *i2;
definen punteros a a const int
. Puede cambiar dónde i1
y i2
puntos, pero no puede cambiar el valor al que apuntan.
Esta:
int *const i3 = (int*) 0x12345678;
define un const
puntero a un entero y lo inicializa para apuntar a la ubicación de memoria 12345678. Puede cambiar el int
valor en la dirección 12345678, pero no puede cambiar la dirección a la que i3
apunta.
const * char
es 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* const
es un puntero constante a un caracter
const char* const
es un puntero constante a un caracter constante
Regla de oro: ¡ lea la definición de derecha a izquierda!
const int *foo;
Significa " foo
puntos ( *
) a un int
que no puede cambiar ( const
)".
Para el programador esto significa "no cambiaré el valor de lo que foo
apunta".
*foo = 123;
o foo[0] = 123;
sería inválidofoo = &bar;
esta permitido.int *const foo;
Significa " foo
no puede cambiar ( const
) y puntos ( *
) a int
".
Para el programador esto significa "No cambiaré la dirección de memoria que se foo
refiere".
*foo = 123;
o foo[0] = 123;
está permitido.foo = &bar;
Sería inválido.const int *const foo;
Significa " foo
no puede cambiar ( const
) y apunta ( *
) a un int
que no puede cambiar ( const
)".
Para el programador esto significa "no cambiaré el valor de lo que foo
apunta, ni cambiaré la dirección a la que se foo
refiere".
*foo = 123;
o foo[0] = 123;
sería inválidofoo = &bar;
Sería inválido.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 .
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:
En sentido horario / regla espiral
UNA)
const char *a;
Según la regla en sentido horario / espiral, el a
puntero 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, a
es un puntero constante a un personaje. es decir, puedes hacer a[2] = 'c';
pero no puedes hacera = "other string";
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.
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 1
char ca2[10]= "bbbb"; // char array 2
char *pca1= ca1;
char *pca2= ca2;
char const *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’
char const **ccss= &ccs; // Good
char const **ccss1= &csc; // Bad - warning: initialization from incompatible pointer type
char * const *cscs= &csc; // Good
char * const *cscs1= &ccs; // Bad - warning: initialization from incompatible pointer type
char ** const cssc= &pca1; // Good
char ** const cssc1= &ccs; // Bad - warning: initialization from incompatible pointer type
char ** 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’
}
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);
return 0;
}
Sintaxis:
const datatype *var
o 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;
int const *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*/
return 0;
}
char * const y const char *?
const char * p;
// el valor no se puede cambiar
char * const p;
// la dirección no se puede cambiar
const char * const p;
// ambos no se pueden cambiar.
El const
modificador 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 * const
const char const *
char const * const
char const const *
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 int
variable, sino que esta variable es const
para este puntero específico.
Por ejemplo:
int var = 10;
int const * _p = &var;
El código anterior se compila perfectamente bien. _p
apunta a una const
variable, aunque en var
sí misma no es constante.
Recuerdo del libro checo sobre C: lea la declaración de que comienza con la variable y vaya a la izquierda. Entonces para
char * const a;
puede leer como: " a
es una variable de tipo puntero constante a char
",
char const * a;
puede leer como: " a
es un puntero a una variable constante de tipo char. Espero que esto ayude.
Prima:
const char * const a;
Leerá como a
es un puntero constante a una variable constante de tipo char.