Спасибо.Я много занимаюсь программированием на С, и это действительно странно, что я никогда с этим не сталкивался.
Возможно, потому что вы не понимаете, что существуют разные способы хранения C-String.Возможно, вам повезло, что вы никогда не сталкивались с segfault из-за этого.
Строковые литералы
Строковый литерал объявляется с двойными кавычками, например
"hello world"
Эта строка обычно хранится в разделе только для чтения.При использовании строковых литералов лучше всего объявлять переменные с const
следующим образом:
const char *str = "hello world";
При этом вы знаете, что str
указывает на область памяти только для чтения, и вы не можете манипулировать содержимымстроки.Фактически, если вы сделаете это:
const char *str = "hello world";
str[0] = 'H';
// or the equivalent
*str = 'H'
, компилятор выдаст ошибку, подобную этой:
a.c:5:5: error: assignment of read-only location ‘*str’
, что я нашел очень полезным, потому что вы не можете случайно манипулировать содержимым, на которое указываетby str
.
Массивы
Если вам нужно манипулировать содержимым строки, вам нужно сохранить строку в массиве, например,
char str[] = "hello word";
В этом случае компилятор знает, что строковый литерал имеет 10 символов, и резервирует 11 байтов (1 байт для '\0'
- завершающий байт) для str
и инициализирует массив содержимым строкового литерала..
Здесь вы можете делать такие вещи, как
str[0] = 'H'
, но вы не можете получить доступ после 11-го байта.
Вы также можете объявить массив с фиксированным размером.В этом случае размер должен быть как минимум равен длине + 1 строкового литерала.
char str[11] = "Hello world";
Если вы объявите меньше места (например, char str[3] = "hello world";
), ваш компилятор предупредит вас чем-нибудькак это
a.c:4:14: warning: initializer-string for array of chars is too long
но я не уверен, что произойдет, если вы все равно выполните код.Я думаю, что это случай неопределенного поведения, и это означает, что может случиться что угодно.
Лично я обычно объявляю свою строку без фиксированного размера, если только нет причины иметь фиксированный размер.