Esta es una pregunta muy básica, pero no encontré una respuesta clara. Trato de entender cómo funcionan los literales de cadena en C
#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char *str = "Hello World!"; str = "Reassign str."; char *str2 = "Something."; str = strdup(str2); free(str); exit(EXIT_SUCCESS); } Cuando hago str = "Reassign str." o str = strdup(str2) a un literal de cadena, ¿qué sucede con la cadena Hello World ? ¿Es parte del ejecutable, queda fuera del alcance, se libera la memoria después de reasignar str ?
Los literales de cadena tienen una duración de almacenamiento estática. No se destruyen y tienen las mismas direcciones durante la ejecución del programa.
En estas declaraciones
str = "Reassign str."; //... str = strdup(str2); el puntero str solo es reasignado por algunas otras direcciones. En la primera declaración, obtiene la dirección del primer carácter del literal de cadena "Reassign str". y en la segunda instrucción obtiene la dirección de la memoria asignada dinámicamente para la matriz de caracteres que contiene una copia de la cadena literal a la que apunta str2.
De acuerdo con el Estándar C (6.4.5 Literales de cadena)
6 En la fase de traducción 7, se agrega un byte o código de valor cero a cada secuencia de caracteres multibyte que resulta de una cadena literal o literales. para contener la secuencia. Para los literales de cadena de caracteres, los elementos de la matriz tienen el tipo char y se inicializan con los bytes individuales de la secuencia de caracteres multibyte.
Y (6.2.4 Duraciones de almacenamiento de objetos)
3 Un objeto ... tiene una duración de almacenamiento estática. Su tiempo de vida es la ejecución completa del programa y su valor almacenado se inicializa solo una vez, antes del inicio del programa.
En cuanto a los literales de cadena en sí, no puede cambiarlos. Cualquier intento de cambiar un literal de cadena da como resultado un comportamiento indefinido del programa.
Del estándar C (6.4.5 Literales de cadena)
7 No se especifica si estas matrices son distintas siempre que sus elementos tengan los valores apropiados. Si el programa intenta modificar una matriz de este tipo, el comportamiento no está definido.
Por ejemplo, no puede escribir
char *str = "Hello World!"; *str = 'h';Cuando tu lo hagas
char *str = "Hello World!"; el compilador reserva memoria de bytes strlen(str) + 1 para ese literal de cadena. Cuando se reasigna el puntero str , la memoria asignada para el literal de cadena "Hello World!" no se destruye/libera, sino que persiste en su ámbito.
Todo está bien en tu código.
char *str = "Hello World!"; Ok, declaras un char * que apunta a una cadena litteral. Para ser correcto, debería haber escrito const char *str = porque una cadena litteral es una cadena no modificable ( str[4] = 'u'; sería incorrecto)
str = "Reassign str.";Ok, el puntero str ahora apunta a otra cadena literal. La misma observación que la anterior, aún debe ser const.
char *str2 = "Something.";Todavía la misma historia
str = strdup(str2); Ahora str apunta a una cadena mallada. Por primera vez es correcto que str no sea const. str[0] = 's'; sería correcto aquí.
free(str); Bien, liberas la cadena asignada por strdup .
exit(EXIT_SUCCESS);Devuelve muy bien un valor definido (0) al entorno.