¿Por qué los literales de cadena (char*) en C++ tienen que ser constantes?

5 minutos de lectura

avatar de usuario
Serket

Recientemente estuve aprendiendo C++ y me di cuenta de que los literales de cadena en C++ tienen que ser constantes, mientras que en C no lo son. Aquí hay un ejemplo. El siguiente código sería válido en C, pero no en C++:

char* str = "Hello World";

para hacer lo mismo en C++, se debe usar la siguiente declaración:

const char* str = "Hello World";

¿Alguien podría explicar por qué?

  • “mientras que en C, no lo hacen” Eres incorrecto. Los literales de cadena en C son constantes, pero se les permite señalarlos mediante un char*. Todavía no puede modificar la cadena a través de ese puntero. En C++, simplemente eliminaron esa excepción a la corrección constante para evitar confusiones y errores.

    – François Andrieux

    4 mayo 2020 a las 21:26


  • Porque así diseñaron el lenguaje. C inicialmente no tenía la const palabra clave, por lo que rompería el código heredado si cambiaran los literales para requerir const-calificación después de la introducción de la palabra clave. Sin embargo, los literales de cadena de C son inmutables, por lo que cambiar el contenido es un comportamiento indefinido, incluso si no es const-calificado.

    – Christian Gibbons

    4 mayo 2020 a las 21:26


  • @ChristianGibbons, entonces, ¿por qué funciona el siguiente código? “char* str = “Hola Mundo”; str = “Adiós Mundo”;“`

    – Serket

    4 mayo 2020 a las 21:28


  • @Serket: Eso no modifica la cadena en sí; está cambiando el puntero str (que no es una constante) para apuntar a una cadena diferente. char *str = "Hello World"; str[0] = 'J'; sería un comportamiento indefinido.

    – Nate Eldredge

    4 mayo 2020 a las 21:29

  • @FrançoisAndrieux, probablemente deberías copiar eso en una respuesta.

    – Marco Bonelli

    4 mayo 2020 a las 21:30

Ampliando un poco la respuesta de Christian Gibbons…

En C, los literales de cadena como "Hello World" se almacenan en arreglos de char de modo que sean visibles durante la vida útil del programa. Los literales de cadena son supuesto ser inmutable, y algunas implementaciones los almacenarán en un segmento de memoria de solo lectura (de modo que intentar modificar el contenido del literal desencadenará un error de tiempo de ejecución). Algunas implementaciones no lo hacen, y es posible que intentar modificar el contenido del literal no desencadene un error de tiempo de ejecución (incluso puede parecer que funciona según lo previsto). La definición del lenguaje C deja el comportamiento “indefinido” para que el compilador sea libre de manejar la situación como mejor le parezca.

En C++, los literales de cadena se almacenan en arreglos de const charde modo que cualquier intento de modificar el contenido del literal desencadenará un diagnóstico en tiempo de compilación.

Como señala Christian, la const La palabra clave originalmente no era parte de C. Sin embargo, originalmente era parte de C ++, y hace que el uso de cadenas literales sea un poco más seguro.

Recuerda que el const palabra clave no es significa “almacenar esto en la memoria de solo lectura”, solo significa “es posible que esta cosa no sea el objetivo de una asignación”.

Recuerde también que, a menos que sea el operando del sizeof o unario * operadores, o es un literal de cadena utilizado para inicializar una matriz de caracteres en una declaración, un expresión de tipo “arreglo de elementos N de T” se convertirá (“decay”) en una expresión de tipo “puntero a T” y el valor de la expresión será la dirección del primer elemento de la matriz.

En C++, cuando escribes

const char *str = "Hello, world";

la dirección del primer carácter de la cadena se almacena en str. Puedes configurar str señalar a un diferente literal de cadena:

str = "Goodbye cruel world";

pero que tu no poder hacer es modificar el contenido de la cadena, algo así como

str[0] = 'h';

o

strcpy( str, "Something else" );

  • OMI una respuesta correcta. Probablemente enfatizaría más eso en const char *s="foo"; la const dice algo solo sobre el puntero (no se puede usar para escribir), pero no dice nada sobre el objeto señalado. Desafortunadamente, muchos programadores de C++ (e incluso la biblioteca estándar) confunden los dos especialmente con referencias (es decir, en const X& x la palabra clave const es relativo a la referencia solo y no dice nada sobre el objeto al que se hace referencia; pasando un const& es no una forma inteligente de pasar por valor, ya que puede encontrarse con problemas de por vida o de alias).

    – 6502

    6 de mayo de 2020 a las 6:08

  • @6502: const char *str significa que el objeto apuntado es const, no el puntero. Podemos escribir un nuevo valor para str (apúntelo a un objeto diferente), pero no a *str o str[i]. char * const str significa que el puntero mismo es const y no se puede escribir, pero la cosa a la que apunta sí.

    – Juan Bode

    6 de mayo de 2020 a las 10:58

  • No. La declaración const char *str; es una declaración de un “puntero de solo lectura”, es decir, un puntero que puede usarse solo para lectura… pero esa es una propiedad del puntero, no dice nada sobre la constancia del objeto apuntado. El objeto puntiagudo puede cambiar, simplemente no se puede cambiar. usando ese puntero (pero puede haber, por ejemplo, otros punteros de lectura/escritura al mismo objeto). UN const char * no es un puntero a char que es constante, es un puntero a un char que no se puede usar para escribir.

    – 6502

    6 de mayo de 2020 a las 12:56

  • @6502: =*suspiro*= Tienes razón, aún no había tomado mi café.

    – Juan Bode

    8 de mayo de 2020 a las 14:05

  • @Splines: código como char x = 'A'; const char *p = &x; printf("%c\n", *p); x = 'B'; printf("%c\n", *p); es perfectamente válido y la salida debe ser A\nB\n (ver godbolt.org/z/rjx64TjMG). Asi que p no es un apuntador a una constante porque lo que apunta cambia! Seguro que no puedes cambiarlo usando p (sin yeso) pero esto no hace que el objeto puntiagudo sea una constante en el sentido absoluto. p es un puntero que no se puede usar para escribir (es por eso que preferiría “puntero de solo lectura”). Tenga en cuenta sin embargo que literales de cadena SON constantes, por lo que tratar de modificarlas es UB.

    – 6502

    7 ene a las 20:53

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad