'р' 'о', 'к', 'о', 'й', ' .', '\0'};
(Обратите внимание на замыкающий нуль-символ. Без него мы имеем массив символов, а не строку.) Для той и другой формы (а мы рекомендуем первую) компилятор подсчитывает символы и таким образом получает размер массива.
Как и для других массивов, имя m1является указателем на первый элемент массива:
m1 == &m1[0], *m1 == 'Т', и *(m1 + l) == m1[1] == 'о',
Действительно, мы можем использовать указатель для создания строки. Например:
char *m3 = " \n Достаточно обо мне - как вас зовут?";
Это почти то же самое, что и
static char m3[ ] = "\n Достаточно обо мне - как вас зовут?" ;
Оба описания говорят об одном: m3является указателем строки со словами " Как вас зовут?" . В том и другом случае сама строка определяет размер памяти, необходимой для ее размещения. Однако вид их не идентичен.
В чем же тогда разница между этими двумя описаниями? Описание с массивом вызывает создание в статической памяти массива из 38 элементов (по одному на каждый символ плюс один на завершающий символ ' \0'. Каждый элемент инициализируется соответствующим символом. В дальнейшем компилятор будет рассматривать имя m3как синоним адреса первого элемента массива, т. е. & m3[0]. Следует отметить, что m3является константой указателя. Вы не можете изменить m3, так как это означало бы изменение положения (адрес) массива в памяти. Можно использовать операции, подобные m3+1, для идентификации следующего элемента массива, однако нe разрешается выражение ++m3. Опeратор увеличения можно использовать с именами переменных, но не констант.
Форма с указателем также вызывает создание в статической памяти 38 элементов для запоминания строки. Но, кроме того, выделяется еще одна ячейка памяти для переменной m3, являющейся указателем. Сначала эта переменная указывает на начало строки, но ее значение может изменяться. Поэтому мы можем использовать операцию увеличения; ++m3будет указывать на второй символ строки ( Д). Заметим, что мы не объявили *m3статической неременной, потому что мы инициализировали не массив из 38 элементов, а одну переменную типа указатель. Не существует ограничений на класс памяти при инициализации обычных переменных, не являющихся массивом.
Существенны ли эти отличия? Чаще всего нет, но все зависит от того, что вы пытаетесь делать. Посмотрите несколько примеров, а мы возвращаемся к вопросу выделения памяти для строк.
Массив и указатель: различия
В нижеследующем тексте мы обсудим различия в использовании описаний этих двух видов:
static char heart[ ] ="Я люблю Тилли !";
char *head ="Я люблю Милли!";
Основное отличие состоит в том, что указатель heartявляется константой, в то время как указатель head- переменной. Посмотрим, что на самом деле даст эта разница.
Вo-пepвых, и в том и в другом случае можно использовать операцию сложения с указателем.
for(i = 0; i < 6; i++ )
putchar(*(heart + i));
putchar('\n');
for(i = 0; i < 6; i++ )
putchar(*(head + i));
putchar('\n');
в результате получаем
Я люблю Я люблю
Но только в случае с указателем можно использовать операцию увеличения:
while( *(head) != '\0') /* останов и конце строки */
putchar(*(head++ )); /* печать символа и перемещение указателя */
дают в результате:
Я люблю МИЛЛИ!
Предположим, мы хотим заменить headна heart. Мы можем cказать
head = heart /* теперь head указывает на массив hеart */
но теперь мы можем сказать
heart = head; /* запрещенная конструкция */
Ситуация аналогична х = 3или 3 = х;левая часть оператора присваивания должна быть именем переменной. В данном случае head = heart;не уничтожит строку Милли, а только изменит адрес, записанный в head. Вот каким путем можно изменить обращение к heartи проникнуть в сам массив:
heart[8] = 'М';
или
*(heart + 8) = 'М';
Элементы массива (но не имя ) являются переменными
Явное задание размера памяти
Иной путь выделения памяти заключается в явном ее задании. Во внешнем описании мы могли бы скачать:
char m1[44] = "Только ограничьтесь одной строкой.";
вместо
char m1[ ] = "Только ограничьтесь одной строкой.";
Можно быть уверенным, что число элементов по крайней мере на один (это снова нуль-символ) больше, чем длина строки. Как и в других статических или внешних массивах, любые неиспользованные элементы автоматически инициализируются нулем (который в символьном виде является нуль-символом, а не символом цифры нуль).
Читать дальше