2009-04-05 10 views
8

Tengo algunas dudas sobre cadenas literales en C++.String Literals

char *strPtr ="Hello" ; 
char strArray[] ="Hello"; 

Ahora strPtr y strArray se consideran literales de cadena.

Según mi comprensión, los literales de cadena se almacenan en la memoria de solo lectura, por lo que no podemos modificar sus valores.

No podemos hacer

strPtr[2] ='a'; 
and strArray[2]='a'; 

Tanto las declaraciones anteriores deben ser ilegal. El compilador debe arrojar errores en ambos casos.

El compilador guarda los literales de cadena en la memoria de solo lectura, por lo que si intentamos modificarlos, el compilador arroja errores.

También los datos de const también se consideran de solo lectura.

¿Es que ambos literales de cadena y datos de const se tratan de la misma manera? ¿Puedo eliminar la constancia usando const_cast de string literal puede cambiar su valor?

¿Dónde exactamente se almacenan los literales de cadena? (en la sección de datos del programa)

Respuesta

16

Ahora strPtr y strArray se consideran literales de cadena.

No, no lo son. Los literales de cadena son las cosas que ves en tu código. Por ejemplo, el "Hello". strPtr es un puntero al literal (que ahora se compila en el ejecutable). Tenga en cuenta que debe ser const char *; no se puede eliminar legalmente el const según el estándar C y se espera un comportamiento definido al usarlo. strArray es una matriz que contiene una copia del literal (compilado en el ejecutable).

Ambas declaraciones anteriores deberían ser ilegales. el compilador debe lanzar errores en ambos casos.

No, no debería. Las dos declaraciones son completamente legales. Debido a las circunstancias, el primero no está definido. Sin embargo, sería un error si fueran punteros a const char s.

Hasta donde yo sé, los literales de cadena se pueden definir de la misma manera que otros literales y constantes. Sin embargo, existen diferencias:

// These copy from ROM to RAM at run-time: 
char myString[] = "hello"; 
const int myInt = 42; 
float myFloats[] = { 3.1, 4.1, 5.9 }; 

// These copy a pointer to some data in ROM at run-time: 
const char *myString2 = "hello"; 
const float *myFloats2 = { 3.1, 4.1, 5.9 }; 

char *myString3 = "hello"; // Legal, but... 
myString3[0] = 'j';   // Undefined behavior! (Most likely segfaults.) 

Mi uso de la ROM y la RAM aquí son generales. Si la plataforma es solo RAM (por ejemplo, la mayoría de los programas de Nintendo DS), const data puede estar en la memoria RAM. Las escrituras aún no están definidas. La ubicación de los datos de const no debería importar para un programador de C++ normal.

8
char *strPtr ="Hello" ; 

Define strPtr un puntero a char que apunta a una cadena literal "Hello" - el tipo efectivo de este puntero es const char *. No se permiten modificaciones a través del strPtr al punto (invoca UB si intenta hacerlo). Esta es una característica de compatibilidad con versiones anteriores para el código C anterior.Esta convención está en desuso en C++ 0x. Ver Anexo C:

Cambio: Los literales de cadena hechas const El tipo de una cadena literal se cambia de “arreglo de char” a “arreglo de char const.” [...]

Justificación: Esto evita llamar a una función sobrecargada inapropiada, que podría esperar poder modificar su argumento.

Efecto en la función original: Cambio a la semántica de la función bien definida. Dificultad de conversión: transformación sintáctica simple, porque los literales de cadena pueden convertirse a char *; (4.2). Los casos más comunes son manejados por una nueva aunque no se use conversión estándar:

char* p = "abc"; // valid in C, deprecated in C++

char* q = expr ? "abc" : "de"; // valid in C, invalid in C++

Cómo ampliamente utilizado: Los programas que tienen una razón legítima para tratar los literales de cadena como punteros a la memoria potencialmente modificable son probablemente raros.

char strArray[] ="Hello"; 

El tipo declarado de strPtr es - es una matriz de caracteres de tamaño no especificado que contienen la cadena Hello incluyendo el nulo terminador es decir 6 caracteres. Sin embargo, la inicialización lo convierte en un tipo completo y su tipo es una matriz de 6 caracteres. La modificación a través de strPtr está bien.

¿Dónde exactamente se almacenan los literales de cadena?

Implementación definida.

+0

"El tipo declarado de strPtr es", ¿te refieres a strArray? – 4pie0

1

Los más viejos compiladores de C y C++ se basa puramente en la codificación de bajo nivel donde los estándares más altos de protección de datos no estaban disponibles, y ni siquiera pueden hacerse cumplir, por lo general en C y C++ se puede escribir lo que quieras ..

Incluso puede escribir un código para acceder y modificar sus punteros const, si sabe cómo jugar con las direcciones.

Aunque C++ impone alguna protección de nivel de compilación, pero no hay protección en el tiempo de ejecución. Sin duda, puede acceder a su propia pila y utilizar sus valores para manipular cualquier dato que entre en el puntero de const. Esa es la razón por la cual se aplica C# donde se aplican estándares de nivel superior porque cualquier referencia es una estructura fija que rige todas las reglas de protección de datos y tiene un puntero oculto al que no se puede acceder ni modificar.

La principal diferencia es que C++ solo puede ofrecerle protección de tiempo de compilación, pero C# le brindará protección incluso en tiempo de ejecución.

Cuestiones relacionadas