Cuando escribe una "cadena" en su código fuente, se escribe directamente en el ejecutable porque ese valor debe conocerse en el momento de la compilación (hay herramientas disponibles para separar el software y encontrar todas las cadenas de texto sin formato). Cuando escribe char *a = "This is a string"
, la ubicación de "Esto es una cadena" está en el ejecutable, y la ubicación a la que a
apunta, está en el ejecutable. Los datos de la imagen ejecutable son de solo lectura.
Lo que debe hacer (como han señalado las otras respuestas) es crear esa memoria en una ubicación que no sea de solo lectura, en el montón o en el marco de la pila. Si declara una matriz local, se crea espacio en la pila para cada elemento de esa matriz, y el literal de cadena (que se almacena en el ejecutable) se copia en ese espacio en la pila.
char a[] = "This is a string";
también puede copiar esos datos manualmente asignando algo de memoria en el montón y luego usar strcpy()
para copiar un literal de cadena en ese espacio.
char *a = malloc(256);
strcpy(a, "This is a string");
Siempre que asigne espacio usando malloc()
recuerde llamar free()
cuando haya terminado (lea: pérdida de memoria).
Básicamente, debes realizar un seguimiento de dónde están tus datos. Cada vez que escribe una cadena en su fuente, esa cadena es de solo lectura (de lo contrario, estaría cambiando potencialmente el comportamiento del ejecutable; imagínese si escribió char *a = "hello";
y luego cambió a[0]
a 'c'
. Luego, en otro lugar escribió printf("hello");
. Si se le permitiera cambiar el primero carácter de "hello"
, y su compilador solo lo almacenó una vez (debería), ¡luego printf("hello");
saldría cello
!
No, no puede modificarlo, ya que la cadena se puede almacenar en la memoria de solo lectura. Si desea modificarlo, puede usar una matriz en su lugar, por ejemplo,
char a[] = "This is a string";
O alternativamente, puede asignar memoria usando malloc, por ejemplo
char *a = malloc(100); strcpy(a, "This is a string"); free(a); // deallocate memory once you've done
fuente
Mucha gente se confunde acerca de la diferencia entre char * y char [] junto con los literales de cadena en C. Cuando escribe:
char *foo = "hello world";
... en realidad está apuntando a foo a un bloque constante de memoria (de hecho, lo que hace el compilador con "hola mundo" en este caso depende de la implementación).
El uso de char [] en su lugar le dice al compilador que desea crear una matriz y llenarla con el contenido, "hola mundo". foo es el puntero a al primer índice de la matriz char. Ambos son punteros char, pero solo char [] apuntará a un bloque de memoria mutable y asignado localmente.
fuente
Usted no asigna la memoria para a & b. El compilador es libre de elegir una ubicación de memoria de solo lectura para almacenar los caracteres. Entonces, si intenta cambiarlo, puede resultar en una falla seg. Así que le sugiero que cree una matriz de caracteres usted mismo. Algo como:
char a[10]; strcpy(a, "Hello");
fuente
Parece que su pregunta ha sido respondida, pero ahora se preguntará por qué char * a = "String" se almacena en la memoria de solo lectura. Bueno, en realidad no está definido por el estándar c99, pero la mayoría de los compiladores lo eligen de esta manera para casos como:
printf("Hello, World\n");
c99 estándar (pdf) [página 130, sección 6.7.8]:
La declaracion:
char s[] = "abc", t[3] = "abc";
define objetos de matriz de caracteres "simples" syt cuyos elementos se inicializan con literales de cadena de caracteres. Esta declaración es idéntica a char
s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' };
El contenido de las matrices se puede modificar. Por otro lado, la declaración
char *p = "abc";
define p con el tipo "pointer to char" y lo inicializa para apuntar a un objeto con el tipo "array of char" con longitud 4 cuyos elementos se inicializan con una cadena de caracteres literal. Si se intenta utilizar p para modificar el contenido de la matriz, el comportamiento no está definido.
fuente
También puede utilizar
strdup
:The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory for the new string is obtained with malloc(3), and can be freed with free(3).
Por tu ejemplo:
char *a = strdup("stack overflow");
fuente
strdup
. Sin embargo, no estoy seguro de cuándo querría usarlo.var = malloc(strlen(str) + 1); strcpy(var, str);
, probablemente debas usarstrdup
en su lugar.Todas son buenas respuestas que explican por qué no puede modificar los literales de cadena porque se colocan en la memoria de solo lectura. Sin embargo, cuando las cosas se ponen difíciles, hay una manera de hacerlo. Mira este ejemplo:
#include <sys/mman.h> #include <unistd.h> #include <stddef.h> #include <string.h> #include <stdlib.h> #include <stdio.h> int take_me_back_to_DOS_times(const void *ptr, size_t len); int main() { const *data = "Bender is always sober."; printf("Before: %s\n", data); if (take_me_back_to_DOS_times(data, sizeof(data)) != 0) perror("Time machine appears to be broken!"); memcpy((char *)data + 17, "drunk!", 6); printf("After: %s\n", data); return 0; } int take_me_back_to_DOS_times(const void *ptr, size_t len) { int pagesize; unsigned long long pg_off; void *page; pagesize = sysconf(_SC_PAGE_SIZE); if (pagesize < 0) return -1; pg_off = (unsigned long long)ptr % (unsigned long long)pagesize; page = ((char *)ptr - pg_off); if (mprotect(page, len + pg_off, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) return -1; return 0; }
He escrito esto como parte de mis pensamientos algo más profundos sobre la corrección de constantes , lo que puede resultarle interesante (espero :)).
Espero eso ayude. ¡Buena suerte!
fuente
Debe copiar la cadena en otro búfer de memoria que no sea de solo lectura y modificarlo allí. Utilice strncpy () para copiar la cadena, strlen () para detectar la longitud de la cadena, malloc () y free () para asignar dinámicamente un búfer para la nueva cadena.
Por ejemplo (C ++ como pseudocódigo):
int stringLength = strlen( sourceString ); char* newBuffer = malloc( stringLength + 1 ); // you should check if newBuffer is 0 here to test for memory allocaton failure - omitted strncpy( newBuffer, sourceString, stringLength ); newBuffer[stringLength] = 0; // you can now modify the contents of newBuffer freely free( newBuffer ); newBuffer = 0;
fuente
char *a = "stack overflow"; char *b = "new string, it's real"; int d = strlen(a); b = malloc(d * sizeof(char)); b = strcpy(b,a); printf("%s %s\n", a, b);
fuente