char * word = "дело";
Можно ли применить указатель для изменения этой строки?
word[2] = [n]; // допустимо??
Ваш компилятор может разрешить подобное, но согласно текущему стандарту С, поведение в этом случае не определено. Такой оператор может, например, привести к ошибке доступа в память. Причина связана с тем, что, как упоминалось ранее, компилятор может выбрать вариант представления всех идентичных строковых литералов в виде единственной копии в памяти. Например, все приведенные ниже операторы могут ссылаться на единственную ячейку памяти, в которой хранится строка "Клинтон":
char * p1 = "Клинтон";
р1[0] = 'Ф'; // все ли правильно?
printf("Клинтон");
printf(": берегитесь %sueB!\n", "Клингон");
Это значит, что компилятор может заменить каждый экземпляр строкового литерала "Клингон" одним и тем же адресом. Если компилятор использует представление в виде единственной копии и разрешит произвести замену p1[0] на ' Ф', то это затронет все случаи использования данной строки, поэтому операторы, выводящие строковый литерал "Клингон", в действительности отобразят строку "Флингон":
Клинтон: берегитесь Флингонцев!
На самом деле в прошлом некоторые компиляторы вели себя таким путающим образом, в то время как другие генерировали программы, которые в подобных случаях завершались аварийно. Поэтому рекомендуется при инициализации указателя строковым литералом применять модификатор const:
const char * p1 = "Клингон"; // рекомендуемое использование
Тем не менее, инициализация строковым литералом массива, отличного const, не влечет за собой проблем такого рода, поскольку массив получает копию исходной строки.
Короче говоря, не используйте указатель на строковый литерал, если вы планируете изменять строку.
Массивы символьных строк
Часто удобно иметь массив символьных строк. Тогда для доступа к разным строкам можно применять индекс. В листинге 11.4 продемонстрированы два подхода: массив указателей на строки и массив из массивов типа char.

Символьные строки и строковые функции 427
размер mytalents: 40, размер yourtalents: 200
Во многих отношениях массивы mytalents и yourtalents очень похожи. Каждый представляет по пять строк. Когда используется один индекс, как в mytalents [0] и yourtalents [0], результатом будет одиночная строка. Подобно тому, как значением mytalents [1] [2] является ' ч', т.е. третий символ во второй строке, представленной массивом mytalents, yourtalents [1] [2] — это 'ж', т.е. третий символ второй строки, представленной массивом yourtalents. Оба массива инициализируются в одинаковой манере.
Но имеются и различия. Массив mytalents — это массив из пяти указателей, занимающий в нашей системе 40 байтов. Но yourtalents — массив, состоящий из пяти массивов по 40 значений char и занимающий в нашей системе 200 байтов. Таким образом, тип массива mytalents отличается от типа yourtalents, несмотря на то, что и mytalents [0], и yourtalents [0] — это строки. Указатели в mytalents указывают на места размещения строковых литералов, применяемых для инициализации, которые хранятся в статической памяти. Однако массивы в yourtalents содержат копии строковых литералов, в результате чего каждая строка сохраняется дважды.
428 глава 11
Более того, распределение памяти в массивах неэффективно, т.к. все элементы yourtalents должны иметь одинаковый размер, и этот размер должен быть достаточно большим, чтобы вместить самую длинную строку.
Один из способов восприятия этого различия — представление yourtalents в виде прямоугольного двумерного массива, все строки которого имеют одинаковую длину, в данном случае 40 байтов. В то же время mytalents можно представить в виде зубчатого массива с варьирующейся длиной строк. Эти два вида массивов показаны на рис. 11.2. (В действительности строки, на которые указывают элементы массива mytalents, не обязательно должны храниться последовательно в памяти, однако рисунок задуман в качестве иллюстрации различий в требованиях к хранению.)
Смысл всего сказанного в том, что при представлении набора строк, предназначенных для отображения, массив указателей более эффективен, чем массив символьных массивов. Однако существует и ограничение. Поскольку указатели в массиве mytalents указывают на строковые литералы, эти строки не должны изменяться. Тем не менее, содержимое массива yourtalents может изменяться. Поэтому, если предполагается изменение строк или требуется зарезервировать память для ввода строк, не следует использовать указатели на строковые литералы.

Читать дальше