Modificar una cadena con puntero [duplicate]

4 minutos de lectura

avatar de usuario
joumvaer92

Estos dos códigos tienen que cambiar el carácter. 2 en el personaje '4'

int main(int argc, char *argv[]){   
       char *s = "hello";   
       *(s+2)='4';
       printf( "%s\n",s);
       return 0;     
    }

Cuando ejecuto esto, obtengo una falla de segmentación mientras ejecuto esto:

int main(int argc, char *argv[]){   
   char *s = argv[1];   
   *(s+2)='4';
   printf( "%s\n",s);
   return 0;     
}

Sé que hay otros métodos para hacer esto. ¿Cuál es la diferencia entre los 2 programas?

  • ¿De dónde obtienes la falla de seg? en *(s+2)='4'; ?

    –Olivier Poulin

    15 de julio de 2015 a las 14:55

  • Mira aquí: stackoverflow.com/questions/1614723/…

    – cadaniluk

    15 de julio de 2015 a las 14:55

avatar de usuario
Sourav Ghosh

En su primer caso, se enfrenta comportamiento indefinido al intentar modificar un literal de cadena. Una falla de segmentación es una de las más comunes. efectos secundarios de la UB.

En tu código,

 char *s = "hello";

esencialmente pone la dirección inicial del literal de cadena "hello" dentro s. Ahora, si desea modificar el contenido de *s (o *(s+n)proporcionó n no se sale de los límites), en realidad intentará modificar ese literal de cadena. Como de costumbre, los literales de cadena se almacenan en la memoria de solo lectura, son generalmente no se permite modificar. citando de C11capítulo §6.4.5, Literales de cadena, (énfasis mío)

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.

Sin embargo, en tu segundo caso, estás haciendo

 char *s = argv[1];

que es poner el valor de argv[1] dentro s. Ahora, s apunta a la cuerda contenido por argv[1]. Aquí, el contenido de argv[1] (o, argv[n], para ser general) no es de solo lectura, se puede modificar. Entonces, usando *s (o *(s+n)proporcionó n no se sale de los límites), puede modificar los contenidos.

este caso es comportamiento definidoporque según §5.1.2.2.2, Inicio del programa

Los parametros argc y argv y las cuerdas apuntadas por el argv array debe ser modificable por el programay conservan sus últimos valores almacenados entre el inicio y la finalización del programa.

Entonces, el segundo caso es un especial caso durante el uso argv[n]que es, según las reglas estándar de C, modificable.

  • Esta respuesta es para profesionales para personas que hacen este tipo de preguntas.

    – Marek R.

    15 de julio de 2015 a las 14:57

  • @MarekR Lo siento, no te entendí.

    – Sourav Ghosh

    15 de julio de 2015 a las 14:58

  • Para los novatos, esta respuesta es difícil de entender.

    – Marek R.

    15 de julio de 2015 a las 14:59

  • @MarekR En realidad, me gusta citar directamente del estándar para que no haya posibilidad de malentendidos. El inglés no es mi punto fuerte (no es mi lengua materna). ¿Le gustaría proponer alguna adición a esta respuesta para que sea más fácil? estaré agradecido 🙂

    – Sourav Ghosh

    15 de julio de 2015 a las 15:02


  • mucho mejor. Estoy impresionado de que preste tanta atención a este tipo de preguntas.

    – Marek R.

    15 de julio de 2015 a las 17:33

Como dijo Sourav, intentar modificar un literal de cadena invoca un comportamiento indefinido. Si alternativamente hiciera lo siguiente, funcionaría bien.

int main(int argc, char *argv[]){   
   char s[] = "hello";   
   *(s+2)='4';
   printf( "%s\n",s);
   return 0;     
}

Cuando tu lo hagas

char *s = "hello"; 

usted está asignando *s señalar el comienzo de un literal de cadena cual es no modificable. Lo que significa que puedes leer lo que hay pero no puedes cambiarlo (por eso

*(s+2)='4';

te está dando un error de segmentación.

En su segundo caso, no le está dando a su puntero un literal de cadena, por lo que puede modificarlo.

De hecho, en su segundo caso, está utilizando argvcual es específicamente explicado como modificable en el estándar c.

el literal: ‘hola’ está en la memoria de solo lectura, por lo que no se puede cambiar.

Intentar cambiarlo provoca el evento de fallo de segmentación

Intentando cambiar la matriz de cadenas de argv[] tiene el mismo problema. Los valores son de solo lectura

Intentar cambiar un argumento de la línea de comando provoca el evento de falla de segmentación.

Podrías usar: ‘ char s[] = “hola”; ‘ ya que eso pondrá el literal en la pila, donde se puede cambiar.

Puede copiar ‘strcpy ()’ después de obtener la longitud del argumento de la línea de comando y realizar un malloc () para esa longitud + 1

¿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