Sobre esta respuesta de michael-burr en esta pregunta:

qué-es-el-tipo-de-literales-cadena-en-c-y-c

Encontre eso

En C, el tipo de literal de cadena es char []: no es constante de acuerdo con el tipo, pero es un comportamiento indefinido modificar el contenido

A partir de esto, puedo pensar que la oración "How are you" no se puede modificar (igual que char c*="how are you?") pero una vez que se usa para inicializar algunos char[], puede ser a menos que se declare como {{X3} }.

Aparte de esto de esa respuesta:

La secuencia de caracteres multibyte se usa para inicializar una matriz de duración de almacenamiento estático

Y de C Primer Plus 6th Edition encontré:

Las constantes de cadena de caracteres se colocan en la clase de almacenamiento estático, lo que significa que si usa una constante de cadena en una función, la cadena se almacena solo una vez y dura la duración del programa, incluso si la función se llama varias veces

Pero cuando probé este código:

  #include <stdio.h>

  void fun() {
      char c[] = "hello";
      printf("%s\n", c);
      c[2] = 'x';
  }

  int main(void) {
      fun();
      fun();

      return 0;
   }

La matriz dentro de la función fun no se comporta como si hubiera retenido el valor cambiado.

¿Dónde me estoy equivocando en esto?

2
Observer 8 sep. 2018 a las 16:29

3 respuestas

La mejor respuesta

No estás modificando la cadena literal. Está modificando una matriz local que contiene una copia del literal de cadena. Cada vez que llama a fun, se crea e inicializa una nueva instancia de c. Cuando sale fun, esa instancia de c deja de existir.

2
John Bode 8 sep. 2018 a las 13:48

Porque es una variable automática y su instancia se inicializa cada vez que llama a la función.

Cámbielo para tener almacenamiento estático

  static char c[]="hello";

Y se comportará como espera mantener el valor cambiado entre las llamadas a funciones

Esto es algo completamente diferente de cómo se almacenan y usan los literales de cadena y los literales compuestos en la inicialización de la variable. Se deja a la implementación; por ejemplo, esta inicialización de la variable de almacenamiento automático se puede hacer copiando datos del segmento .rodata o puede ser solo un par de instrucciones de almacenamiento inmediatas y el literal se almacenará en el segmento .text

2
P__J__ 8 sep. 2018 a las 13:46

char c[]="hello"; no es lo mismo que char *c="hello";. Este último inicializa un puntero al almacenamiento de cadenas estático mencionado anteriormente, la modificación de c[2] sería un comportamiento indefinido. El primero es equivalente a:

char c[] = {'h', 'e', 'l', 'l', 'o', '\0'};

Está inicializando una matriz en la pila, no está creando una referencia o puntero a la cadena estática en alguna otra ubicación de memoria. Al igual que cualquier otra matriz que no sea const, puede modificarla como quiera (siempre que no salga de los límites).

3
ShadowRanger 8 sep. 2018 a las 13:42