¿Modificar constantes de cadena C?

Posible duplicado:
¿Por qué recibo una falla de segmentación al escribir en una cadena?

Quiero escribir una función que invierta la cadena dada pasada a ella. Pero no puedo. Si proporciono la función doReverse (ver código a continuación) con una matriz de caracteres, mi código funciona bien.

No puedo entender por qué esto no funciona. Puedo acceder a str[0] en doReverse , pero no puedo cambiar ningún valor de la matriz usando un puntero de char. ¿Algunas ideas?

 void doReverse(char *str) { str[0] = 'b'; } void main(void) { char *str = "abc"; doReverse(str); puts(str); } 

Actualizar:

Sé cómo escribir una función inversa pasándole una matriz de caracteres:

 void reverse1(char p[]) { int i, temp, y; for (i = 0, y = strlen(p); i < y; ++i, --y) { temp = p[y-1]; p[y-1] = p[i]; p[i] = temp; } } 

Pero, quiero escribir otra versión que obtenga un puntero char como parámetro.

La solución más simple es cambiar la statement de str a

 char str[] = "abc"; 

Esto hace que str sea ​​una matriz de char que se inicializa a la cadena “abc”. Actualmente tiene str como un puntero a char inicializado para apuntar a una cadena descrita por un literal de cadena. Hay una diferencia clave: los literales de cadena son de solo lectura para dar al comstackdor la máxima flexibilidad sobre dónde almacenarlos; es UB para modificarlos. Pero las matrices de caracteres son mutables, por lo que está bien modificarlas.

PD. main() devuelve un int .

Ya que estás estudiando para un examen, voy a dar forma a mis comentarios un poco para explicar lo que realmente está sucediendo:

 char *str = "abc"; 

str es un puntero almacenado en la stack. Se inicializa para apuntar a la cadena literal "abc" . Esa cadena literal se almacenará en la sección de datos del ejecutable comstackdo y se cargará en la memoria cuando se cargue el progtwig. Esa sección de la memoria es de solo lectura, por lo que cuando intentas modificar los datos apuntados por str, obtienes una infracción de acceso.

 char* str = malloc(sizeof(char) * 4); strcpy(str, "abc"); 

Aquí, str es el mismo puntero de stack que el primer ejemplo. Esta vez, se inicializa para apuntar a un bloque de memoria de 4 caracteres en el montón que puede leer y escribir. Al principio, ese bloque de memoria no está inicializado y puede contener cualquier cosa. strcpy lee el bloque de memoria de solo lectura donde se almacena “abc” y lo copia en el bloque de memoria de lectura y escritura al que apunta str. Tenga en cuenta que establecer str[3] = '\0' es redundante, ya que strcpy ya lo hace.

Por otro lado, si está trabajando en Visual Studio, use strcpy_s para asegurarse de no sobrescribir el búfer si la cadena que se está copiando es más larga de lo que esperaba.

 char str[] = "abc"; 

Aquí str es ahora una matriz asignada en la stack. El comstackdor dimensionará exactamente el literal de cadena utilizado para inicializarlo (incluido el terminador NULL). La memoria de la stack es de lectura-escritura para que pueda modificar los valores en la matriz como lo desee.

 char str[4] = "abc"; 

Esto es efectivamente lo mismo que la versión anterior, solo le está diciendo al comstackdor que usted sabe mejor que cuánto tiempo debe estar la matriz. Puede tener problemas si cambia la cadena y no el tamaño de la matriz.

Debido a que esta es la tarea, daré consejos, pero no publicaré una solución completa.

Supongo que obtendrás una infracción de acceso en str [0] = ‘b’? Esto se debe a que “abc” es una cadena literal.

Copie los puntos Str de cadena antes de llamar al reverso, o obtenga el reverso para asignar un búfer y poner la cadena invertida en eso.

Tenga en cuenta que deberá desasignar toda la memoria que asigne.

Lordy, Lordy Para todos aquellos sugiriendo formas de realizar el intercambio, por favor lea la pregunta cuidadosamente; no hay nada peor que tener que reiterar una pregunta ya perfectamente articulada. Independientemente del método utilizado para implementar el intercambio (temp-swap, xor3-swap, etc.), esta persona parece estar demasiado familiarizada con los elementos intrínsecos fundamentales y bastante elementales de la función.

Sin embargo, como ya se explicó, el comstackdor / vinculador genéricamente coloca todos los literales de cadena dentro del ‘segmento de datos const’ del ejecutable de destino, que posteriormente se asocia con un descriptor MMU no grabable durante la invocación ‘load / exec’ apropiada. Todos los ciclos de escritura de CPU emitidos posteriormente a través de este descriptor quedan atrapados automáticamente por el mecanismo de excepción de la MMU, lo que da como resultado el obligatorio ‘segfault’ o el equivalente específico de la plataforma. Por supuesto, las plataformas antiguas que no son MMU no deberían mostrar ese comportamiento.

Aunque esto efectivamente proporciona soporte en tiempo de ejecución para el idioma ‘constant / literal’ del lenguaje de origen, varias plataformas han facilitado históricamente anulaciones explícitas del segmento en tiempo de comstackción. Sin embargo, este nivel de soporte ha disminuido lentamente a favor de una capa de abstracción más rígida / robusta, lo que hace que muchas optimizaciones obvias ya menudo útiles sean insostenibles. A medida que el tiempo y el desgaste hacen que su filosofía de “MC / ASM” envejezca constantemente antes que una generación de “Microsoft” demasiado ansiosa, los progtwigdores ya no se consideran tan conocedores o responsables como para tomar esta clase de decisión. En lugar de las muchas implementaciones artificiales, por no decir creativas, que presencié como líder de proyecto, esto no es nada malo.

Aunque este post está evolucionando rápidamente hacia una violación fuera de tema, me siento un poco reivindicado por el flujo constante de preguntas de arriba hacia abajo que poco a poco se vuelven endémicas dentro de nuestra industria. Como un principiante progtwigdor de C, un lenguaje originalmente diseñado para complementar el desarrollo de bajo nivel, mi consejo es adoptar un enfoque ascendente y boost sus estudios con un poco de desarrollo del lenguaje ensamblador extracurricular. Como es probable que la implementación algorítmica constituya su enfoque principal como ingeniero de aplicaciones, es importante recordar que el diseño de CPU contemporáneo ha experimentado una evolución homogénea en los últimos 30 años; las CPU ultra rápidas de hoy en día no son más que refinamientos CMOS súper-escalares de los procesadores bipolares de 4/8 bits que estaba progtwigndo cuando la Tierra todavía era joven.

Contrario a la creencia popular, la progtwigción en lenguaje ensamblador es relativamente fácil de aprender, y absolutamente esencial cuando se trata de conciliar construcciones de alto nivel con un comportamiento problemático o esotérico. Una vez que tenga en cuenta las interminables horas de experimentación, depuración, búsqueda en la web y spam de foros, no cabe duda de que un enfoque ascendente es sin duda el camino de menor resistencia.

Buena suerte con sus estudios.

Hasta donde yo sé, las cadenas constantes se implementan como matrices de caracteres constantes (o, en términos C, const char [length] ). Por lo tanto, no puedes modificar sus caracteres.

Intente asignar dinámicamente la cadena.

 char* str = (char*)malloc(sizeof(char) * 4); strcpy(str, "abc"); str[3] = '\0'; 

Por supuesto, no olvides liberar la memoria al final de tu progtwig.


Editar: No publicaré nada relacionado con la inversión de la cadena, porque ese es tu trabajo.