Cuál es la diferencia entre
char* name
que apunta a un literal de cadena constante, y
const char* name
Cuál es la diferencia entre
char* name
que apunta a un literal de cadena constante, y
const char* name
Respuestas:
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, los compiladores deben enviar 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 apuntar a ninguna otra ubicación) pero los contenidos de la ubicación a la que apunta son mutables .
const char* const
es un puntero inmutable a un carácter / cadena inmutable .
char const *
char *
da error de segmentación mientras se ejecuta?
const
si quiero que el compilador dé un error si olvidé y cambié los datos por error, ¿verdad?
char *name
Puede cambiar el carácter a qué name
puntos, y también el carácter al que apunta.
const char* name
Puede cambiar el carácter a qué name
puntos, pero no puede modificar el carácter al que apunta.
corrección: puede cambiar el puntero, pero no el carácter al que name
apunta ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx , consulte "Ejemplos" ) En este caso, el const
especificador se aplica char
, no el asterisco.
De acuerdo con la página de MSDN y http://en.cppreference.com/w/cpp/language/declarations , el const
antes *
es parte de la secuencia de rechazo-especificador, mientras que el const
después *
es parte del declarador.
Una secuencia de especificador de declaración puede ser seguida por múltiples declaradores, razón por la cual const char * c1, c2
declara c1
as const char *
y c2
as const char
.
EDITAR:
A partir de los comentarios, su pregunta parece ser la diferencia entre las dos declaraciones cuando el puntero apunta a un literal de cadena.
En ese caso, no debe modificar el carácter a qué name
puntos, ya que podría dar lugar a un comportamiento indefinido . Los literales de cadena se pueden asignar en regiones de memoria de solo lectura (implementación definida) y un programa de usuario no debe modificarlo de ninguna manera. Cualquier intento 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 declaración le da una ligera ventaja. Los compiladores generalmente le darán una advertencia en caso de que intente modificar el literal de cadena en el segundo caso.
#include <string.h>
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: las advertencias se tratan como errores
prog.c: en la función 'main':
prog.c: 9: error: pasar el argumento 1 de 'strcpy' descarta los calificadores del tipo de destino del puntero
Observe que el compilador advierte para el segundo caso pero no para el primero.
name
apuntan en ninguno de los casos, ya que podría dar lugar a UB.
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
char *
valor da un error de segmentación ya que estamos tratando de modificar un literal de cadena (que está presente en la memoria de solo lectura)
En ningún caso 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 compilador debe dar un diagnóstico si intenta modificar el valor señalado, pero si el puntero es, char *
entonces no lo hace.
extern ... name
y tener *name = 'X';
. En el 'sistema operativo adecuado', eso podría fallar, pero en los sistemas integrados, esperaría que hiciera algo específico para la plataforma / compilador.
CASO 1:
char *str = "Hello";
str[0] = 'M' //Warning may be issued by compiler, and will cause segmentation fault upon running the programme
Lo anterior establece que str apunte al valor literal "Hola", que está codificado en la imagen binaria del programa, que está marcado 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' //Compile time error
CASO 3:
char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".
Lo primero que puedes cambiar realmente si quieres, lo segundo no puedes. Lea sobre la const
corrección (hay algunas buenas guías sobre la diferencia). También hay un lugar char const * name
donde no puedes cambiarlo.
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 pueden verse 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 antiguos que también aceptan en char *
lugar de const char *
, incluso cuando no modifican los argumentos.
La principal diferencia de los 2 en general es que *cname
o cname[n]
evaluará valores de tipo const char
, mientras que *name
o name[n]
evaluará valores de tipo char
, que son valores modificables . Se requiere un compilador conforme para generar un mensaje de diagnóstico si el objetivo de la asignación no es un valor modificable ; no necesita producir ninguna advertencia sobre la asignación a valores de tipo char
:
name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message
El compilador no está obligado a detener la compilación en ninguno de los casos; es suficiente que produzca una advertencia para la asignación cname[0]
. El programa resultante no es un programa correcto . El comportamiento de la construcción es indefinido . Puede bloquearse, o peor aún, podría no bloquearse y cambiar el literal de cadena en la memoria.
En realidad, char* name
no es un puntero a una constante, sino un puntero a una variable. Tal vez estés hablando de esta otra pregunta.