Cuál es la diferencia entre
char* name
que apunta a un literal de cadena constante, y
const char* name
char*
es un puntero mutable a un carácter / cadena mutable .
const char*
es un puntero mutable a un carácter / cadena inmutable . No puede cambiar el contenido de las ubicaciones a las que apunta este puntero. Además, se requiere que los comstackdores den mensajes de error cuando intentas hacerlo. Por la misma razón, la conversión de const char *
a char*
está en desuso.
char* const
es un puntero inmutable (no puede señalar a ninguna otra ubicación) pero el contenido de la ubicación en el que apunta es mutable .
const char* const
es un puntero inmutable para un carácter / cadena inmutable .
char *name
Puede cambiar el carácter al que apunta, y también el carácter al que apunta.
const char* name
Puedes cambiar el carácter al que apunta el name
, pero no puedes modificar el carácter al que apunta.
corrección: puede cambiar el puntero, pero no el carácter al que apunta ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx , consulte “Ejemplos “). En este caso, el especificador const
se aplica a char
, no al asterisco.
De acuerdo con la página de MSDN y http://en.cppreference.com/w/cpp/language/declarations , la const
antes de *
es parte de la secuencia del especificador de declinación, mientras que la const
después de *
es parte del declarador.
Una secuencia de especificador de statement puede ser seguida por múltiples declaradores, por lo que const char * c1, c2
declara c1
como const char *
y c2
como const char
.
EDITAR:
A partir de los comentarios, su pregunta parece estar preguntando sobre la diferencia entre las dos declaraciones cuando el puntero apunta a un literal de cadena.
En ese caso, no debe modificar el carácter al que apunta el name
, ya que podría provocar un comportamiento no definido . Los literales de cadena pueden asignarse en regiones de memoria de solo lectura (implementación definida) y un progtwig de usuario no debería modificarlo de ninguna manera. Cualquier bash de hacerlo da como resultado un Comportamiento Indefinido.
Entonces la única diferencia en ese caso (de uso con literales de cadena) es que la segunda statement le da una ligera ventaja. Los comstackdores generalmente le darán una advertencia en caso de que intente modificar el literal de la cadena en el segundo caso.
Ejemplo de muestra en línea:
#include int main() { char *str1 = "string Literal"; const char *str2 = "string Literal"; char source[] = "Sample string"; strcpy(str1,source); //No warning or error, just Undefined Behavior strcpy(str2,source); //Compiler issues a warning return 0; }
Salida:
cc1: advertencias que se tratan como errores
prog.c: en la función ‘principal’:
prog.c: 9: error: pasar el argumento 1 de ‘strcpy’ descarta los calificadores del tipo de objective de puntero
Observe que el comstackdor advierte para el segundo caso pero no para el primero.
char mystring[101] = "My sample string"; const char * constcharp = mystring; // (1) char const * charconstp = mystring; // (2) the same as (1) char * const charpconst = mystring; // (3) constcharp++; // ok charconstp++; // ok charpconst++; // compile error constcharp[3] = '\0'; // compile error charconstp[3] = '\0'; // compile error charpconst[3] = '\0'; // ok // String literals char * lcharp = "My string literal"; const char * lconstcharp = "My string literal"; lcharp[0] = 'X'; // Segmentation fault (crash) during run-time lconstcharp[0] = 'X'; // compile error // *not* a string literal const char astr[101] = "My mutable string"; astr[0] = 'X'; // compile error ((char*)astr)[0] = 'X'; // ok
En ninguno de los casos puede modificar un literal de cadena, independientemente de si el puntero a ese literal de cadena se declara como char *
o const char *
.
Sin embargo, la diferencia es que si el puntero es const char *
, el comstackdor debe dar un diagnóstico si intenta modificar el valor apuntado, pero si el puntero es char *
no lo hace.
El primero que realmente puede cambiar si lo desea, el segundo no puede. Lea acerca de la exactitud const
(hay algunas buenas guías sobre la diferencia). También hay un char const * name
donde no puede volver a marcarlo.
En realidad, el char* name
no es un puntero a una constante, sino un puntero a una variable. Usted podría estar hablando de esta otra pregunta.
¿Cuál es la diferencia entre char * const y const char *?
CASO 1:
char *str = "Hello"; str[0] = 'M' //No warning or error, just Undefined Behavior
Lo anterior establece str para apuntar al valor literal “Hello”, que está codificado en la imagen binaria del progtwig, que está marcada como de solo lectura en la memoria, significa que cualquier cambio en este literal de Cadena es ilegal y arrojaría fallas de segmentación.
CASO 2:
const char *str = "Hello"; str[0] = 'M' //Compiler issues a warning
CASO 3:
char str[] = "Hello"; str[0] = 'M'; // legal and change the str = "Mello".
Solo para dar un ejemplo extra:
std::cout << typeid(2.3).name() << '\n'; // -----> prints "double" simply because //2.3 is a double //But the "double" returned by typeid(2.3).name() is indeed a //const char * which consists of 'd','o','u','b','l','e'and'\0'. //Here's a simple proof to this: std::cout << typeid(typeid(2.3).name()).name() << '\n'; //prints: "const char *" const char* charptr charptr = typeid(2.3).name(); std::cout << charptr[3]; // ---------> prints: "b"
(Estoy usando la biblioteca typeinfo: http://www.cplusplus.com/reference/typeinfo/type_info/name )
//Now let's do something more interesting: char* charptr2="hubble"; strcpy(charptr, charptr2); // --------> Oops! Sorry, this is not valid!
Puede ejecutarlo y ver las cosas mejor para usted.
La pregunta es ¿cuál es la diferencia entre
char *name
que apunta a un literal de cadena constante, y
const char *cname
Es decir,
char *name = "foo";
y
const char *cname = "foo";
No hay mucha diferencia entre los 2 y ambos se pueden ver como correctos. Debido al largo legado del código C, los literales de cadena han tenido un tipo de char[]
, no const char[]
, y hay muchos códigos anteriores que también aceptan char *
lugar de const char *
, incluso cuando no lo hacen modificar los argumentos.
La principal diferencia de los 2 en general es que *cname
o cname[n]
evaluará a lvalues de tipo const char
, mientras que *name
o name[n]
evaluará a lvalues de tipo char
, que son valores modificables . Se requiere un comstackdor conforme para generar un mensaje de diagnóstico si el objective de la asignación no es un valor l modificable ; no necesita producir ninguna advertencia en la asignación a lvalues de tipo char
:
name[0] = 'x'; // no diagnostics *needed* cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message
El comstackdor no está obligado a detener la comstackción en ningún caso; es suficiente que produzca una advertencia para la asignación a cname[0]
. El progtwig resultante no es un progtwig correcto . El comportamiento de la construcción no está definido . Puede fallar, o incluso peor, puede no bloquearse, y puede cambiar el literal de la cadena en la memoria.