Kiedy piszesz „ciąg” w swoim kodzie źródłowym, jest on zapisywany bezpośrednio w pliku wykonywalnym, ponieważ ta wartość musi być znana w czasie kompilacji (dostępne są narzędzia do rozdzielania oprogramowania i znajdowania w nim wszystkich zwykłych ciągów tekstowych). Kiedy piszesz char *a = "This is a string"
, lokalizacja „To jest ciąg znaków” znajduje się w pliku wykonywalnym, a lokalizacja a
wskazuje na plik wykonywalny. Dane w obrazie wykonywalnym są tylko do odczytu.
To, co musisz zrobić (jak wskazywały inne odpowiedzi), to utworzyć tę pamięć w lokalizacji, która nie jest tylko do odczytu - na stercie lub w ramce stosu. Jeśli deklarujesz tablicę lokalną, na stosie jest tworzona przestrzeń dla każdego elementu tej tablicy, a literał ciągu (który jest przechowywany w pliku wykonywalnym) jest kopiowany do tego miejsca na stosie.
char a[] = "This is a string";
można również skopiować te dane ręcznie, przydzielając część pamięci na stercie, a następnie używając polecenia strcpy()
do skopiowania literału ciągu do tej przestrzeni.
char *a = malloc(256);
strcpy(a, "This is a string");
Za każdym razem, gdy przydzielasz miejsce za pomocą malloc()
pamiętaj, aby zadzwonić, free()
gdy skończysz z nim (czytaj: wyciek pamięci).
Zasadniczo musisz śledzić, gdzie są twoje dane. Za każdym razem, gdy napiszesz ciąg w swoim źródle, ten ciąg jest tylko do odczytu (w przeciwnym razie potencjalnie zmieniłbyś zachowanie pliku wykonywalnego - wyobraź sobie, że napisałeś, char *a = "hello";
a następnie zmieniłeś a[0]
na 'c'
. Potem napisał gdzieś indziej printf("hello");
. Gdybyś mógł zmienić pierwszy znak "hello"
, a Twój kompilator zapisał go tylko raz (powinien), a następnie printf("hello");
wyświetli cello
!)