variable usar strings declarar como caracter c pointers const

usar - Diferencia entre char*y const char*?



strings en c (9)

Cuál es la diferencia entre

char* name

que apunta a un literal de cadena constante, y

const char* name


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 programa, 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".


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 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 compilador debe dar un diagnóstico si intenta modificar el valor apuntado, pero si el puntero es char * no lo hace.



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 compilador conforme para generar un mensaje de diagnóstico si el objetivo 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 compilador no está obligado a detener la compilación en ningún caso; es suficiente que produzca una advertencia para la asignación a cname[0] . El programa resultante no es un programa 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.


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.


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 compiladores 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 declaración 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 programa de usuario no debería 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 la cadena en el segundo caso.

Ejemplo de muestra en línea:

#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: 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 objetivo de puntero

Observe que el compilador 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