Появление отказа сегментации при изменении строки с помощью указателей?

Контекст

Я изучаю C, и я пытаюсь инвертировать строку на месте с помощью указателей. (Я знаю, что можно использовать массив; это больше о приобретении знаний об указателях.)

Проблема

Я продолжаю получать отказы сегментации при попытке выполнить код ниже. GCC, кажется, не нравится *end = *begin; строка. Почему это?

Тем более, что мой код почти идентичен незлу C функция, уже обсужденная в другом вопросе

#include 
#include 

void my_strrev(char* begin){
    char temp;
    char* end;
    end = begin + strlen(begin) - 1;

    while(end>begin){
        temp = *end;
        *end = *begin;
        *begin = temp;
        end--;
        begin++;
    }
}

main(){
    char *string = "foobar";
    my_strrev(string);
    printf("%s", string);
}
10
задан Cœur 26 April 2017 в 16:48
поделиться

3 ответа

Одна проблема лежит с параметром, который вы передаете в функцию:

char *string = "foobar";

Это статическая строка, выделенная в порции только для чтения. Когда вы пытаетесь перезаписать его с

*end = *begin;

, вы получите SegFault.

Попробуйте с

char string[] = "foobar";

, и вы должны заметить разницу.

Основная точка заключается в том, что в первом случае строка существует в сегменте только для чтения, и только указатель на него используется, в то время как во втором случае массив символов с правильным размером зарезервирован на стеке и статическом размере строка (которая всегда существует) копируется в нее. После этого вы свободны изменять содержание массива.

20
ответ дан 3 December 2019 в 14:24
поделиться

Изменение CHAR * String = «FoObar»; - Char String [] = "foobar"; . Проблема в том, что CHAR * точки для чтения только память, которую вы тогда пытаетесь изменять, вызывая ошибку сегментации.

2
ответ дан 3 December 2019 в 14:24
поделиться

В вашем коде есть следующее:

*end--;
*begin++;

Это чистая удача, что это работает правильно (на самом деле, причина в приоритете оператора). Похоже, вы действительно хотели, чтобы код выполнял

(*end)--;
(*begin)++;

Что совершенно неверно. Таким образом, операции выполняются как

  • декремент конец , а затем разыменование его
  • инкремент начало , а затем разыменование его

В обоих случаях разыменование излишне и должен быть удален. Вы, вероятно, задумали, что поведение будет

end--;
begin++;

. Это те вещи, которые заставляют разработчиков задуматься, потому что их так сложно отследить.

4
ответ дан 3 December 2019 в 14:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: