C strtok () и строковые литералы только для чтения

Я думаю, что вы находитесь под доверенностью ... Это случилось со мной в моей повседневной работе, лучший вариант для этого:

  1. Доступ https: // pypi .org / simple /
  2. Найдите свою библиотеку
  3. Загрузите нужную версию ...

Numpy: https://pypi.org/simple/numpy/

5
задан kame 17 September 2019 в 09:42
поделиться

5 ответов

Что Вы инициализировали char * кому?

Если что-то как

char *text = "foobar";

затем у Вас есть указатель на некоторые символы только для чтения

Для

char text[7] = "foobar";

затем у Вас есть семь массивов элемента символов, что можно сделать то, с чем Вы любите.

strtok записи в строку Вы даете его - перезапись символа разделителя с null и хранение указателя на остальную часть строки.

Следовательно при передаче его строка только для чтения это попытается записать в него, и Вы получаете segfault.

Кроме того, becasue strtok сохраняет ссылку на остальную часть строки, это не повторно используемо - можно использовать ее только на одной строке за один раз. Этого лучше всего избегают, действительно - полагают, что strsep (3) вместо этого - видят, например, здесь: http://www.rt.com/man/strsep.3.html (хотя это все еще пишет в строку также - та же проблема read-only/segfault),

15
ответ дан 18 December 2019 в 07:11
поделиться

Важный момент, который выводится, но не указывается явно:

На основании вашего вопроса, я предполагаю, что вы Вы довольно плохо знакомы с программированием на C, поэтому я хотел бы немного подробнее рассказать о вашей ситуации. Прости меня, если я ошибаюсь; C может быть трудно изучить в основном из-за тонкого недопонимания в базовых механизмах, поэтому я хотел бы сделать вещи как можно более понятными.

Как вы знаете, когда вы пишете свою программу на C, компилятор предварительно создает все для вас на основе синтаксис. Когда вы объявляете переменную в любом месте вашего кода, например:

int x = 0;

Компилятор читает эту строку текста и говорит самому себе: ОК, мне нужно заменить все вхождения в текущей области кода x с постоянной ссылкой на область памяти, которую я выделил для хранения целого числа.

Когда ваша программа запускается, эта строка приводит к новому действию: мне нужно установить область памяти, которая x ссылается на значение int 0

Обратите внимание на небольшую разницу: ячейка памяти, которую содержит эталонная точка x , является постоянной (и не может быть изменена). Однако значение, которое указывает x , может быть изменено. Вы делаете это в своем коде посредством присваивания, например x = 15; . Также обратите внимание, что одна строка кода на самом деле составляет две отдельные команды для компилятора.

Когда у вас есть такое выражение:

char * name = "Tom";

Процесс компилятора выглядит следующим образом: OK Мне нужно заменить все вхождения в текущей области кода с именем name постоянной ссылкой на область памяти, которую я выделил для хранения значения указателя char . И это так.

Но есть второй шаг, который сводится к следующему: мне нужно создать постоянный массив символов, который содержит значения 'T', 'o', 'm' и NULL . Затем мне нужно заменить часть кода, которая говорит «Том» , адресом памяти этой константной строки.

Когда ваша программа запущена, происходит последний шаг: установка указателя на значение char (которое не является постоянным) по адресу памяти этой автоматически создаваемой строки (которая является константой ).

Таким образом, char * не только для чтения. Только const char * только для чтения. Но ваша проблема в этом случае не в том, что char * s доступны только для чтения, а в том, что ваш указатель ссылается на области памяти только для чтения.

Я поднимаю все это, потому что понимание этой проблемы - это барьер между тем, как вы смотрите на определение этой функции из библиотеки и понимаете проблему самостоятельно, а не спрашиваете нас. И я несколько упростил некоторые детали в надежде сделать проблему более понятной.

Я надеюсь, что это было полезно. ;)

5
ответ дан 18 December 2019 в 07:11
поделиться

Я обвиняю стандарт C.

char *s = "abc";

возможно, был определен для предоставления той же ошибки как

const char *cs = "abc";
char *s = cs;

на том основании, что строковые литералы являются немодифицируемыми. Но это не было, это было определено для компиляции. Пойди разберись. [Редактирование: Mike B пошел изображенный - "константа" не существовала вообще в K&R C. ISO C, плюс каждая версия C и C++ с тех пор, хотел быть обратно совместимым. Таким образом, это должно быть допустимо.]

Если это было определено для предоставления ошибки, то Вы не могли иметь до segfault, потому что первый параметр strtok является символом*, таким образом, компилятор предотвратил бы Вас передающий в указателе, сгенерированном от литерала.

Это может представлять интерес, что был когда-то план в C++ для этого, чтобы быть удержанным от использования (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1996/N0896.asc). Но 12 лет спустя я не могу убедить или gcc или g ++ дать мне любой вид предупреждения для присвоения литерала к символу неконстанты*, таким образом, это не все, что громко удержало от использования.

[Редактирование: ага: - Wwrite-строки, который не включен в - Стена или-Wextra]

2
ответ дан 18 December 2019 в 07:11
поделиться

Вкратце:

char *s = "HAPPY DAY";
printf("\n %s ", s);

s = "NEW YEAR"; /* Valid */
printf("\n %s ", s);

s[0] = 'c'; /* Invalid */
0
ответ дан 18 December 2019 в 07:11
поделиться

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

0
ответ дан 18 December 2019 в 07:11
поделиться
Другие вопросы по тегам:

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