Строчная константа, как, например, "I AM A STRING" является массивом символов. Компилятор завершает внутреннеепредставление такого массива символом \0, так что программымогут находить его конец. Таким образом, длина массива в па-мяти оказывается на единицу больше числа символов междудвойными кавычками. По-видимому чаще всего строчные константы появляются вкачестве аргументов функций, как, например, в PRINTF ("HELLO, WORLD\N"); когда символьная строка, подобная этой, появляется в прог-рамме, то доступ к ней осуществляется с помощью указателясимволов; функция PRINTF фактически получает указатель сим-вольного массива. Конечно, символьные массивы не обязаны быть только аргу-ментами функций. Если описать MESSAGE как CHAR *MESSAGE; то в результате оператора MESSAGE = "NOW IS THE TIME"; переменная MESSAGE станет указателем на фактический массивсимволов. Это не копирование строки; здесь участвуют толькоуказатели. в языке "C" не предусмотрены какие-либо операциидля обработки всей строки символов как целого. Мы проиллюстрируем другие аспекты указателей и массивов,разбирая две полезные функции из стандартной библиотеки вво-да-вывода, которая будет рассмотрена в главе 7. Первая функция - это STRCPY(S,T), которая копирует стро-ку т в строку S. Аргументы написаны именно в этом порядке поаналогии с операцией присваивания, когда для того, чтобыприсвоить T к S обычно пишут S = T сначала приведем версию с массивами: STRCPY(S, T) /* COPY T TO S */ CHAR S[], T[]; { INT I; I = 0; WHILE ((S[I] = T[I]) != '\0') I++; } Для сопоставления ниже дается вариант STRCPY с указате-лями. STRCPY(S, T) /* COPY T TO S; POINTER VERSION 1 */CHAR *S, *T;{ WHILE ((*S = *T) != '\0') { S++; T++; }} Так как аргументы передаются по значению, функция STRCPYможет использовать S и T так, как она пожелает. Здесь они судобством полагаются указателями, которые передвигаютсявдоль массивов, по одному символу за шаг, пока не будет ско-пирован в S завершающий в T символ \0. На практике функция STRCPY была бы записана не так, какмы показали выше. Вот вторая возможность: STRCPY(S, T) /* COPY T TO S; POINTER VERSION 2 */CHAR *S, *T;{ WHILE ((*S++ = *T++) != '\0') ;} Здесь увеличение S и T внесено в проверочную часть. Зна-чением *T++ является символ, на который указывал T до увели-чения; постфиксная операция ++ не изменяет T, пока этот сим-вол не будет извлечен. Точно так же этот символ помещается встарую позицию S, до того как S будет увеличено. Конечныйрезультат заключается в том, что все символы, включая завер-шающий \0, копируются из T в S. И как последнее сокращение мы опять отметим, что сравне-ние с \0 является излишним, так что функцию можно записать ввиде STRCPY(S, T) /* COPY T TO S; POINTER VERSION 3 */CHAR *S, *T;{ WHILE (*S++ = *T++) ;} хотя с первого взгляда эта запись может показаться загадоч-ной, она дает значительное удобство. Этой идиомой следуетовладеть уже хотя бы потому, что вы с ней будете часто вст-речаться в "C"-программах. Вторая функция - STRCMP(S, T), которая сравнивает сим-вольные строки S и т, возвращая отрицательное, нулевое илиположительное значение в соответствии с тем, меньше, равноили больше лексикографически S, чем T. Возвращаемое значениеполучается в результате вычитания символов из первой пози-ции, в которой S и T не совпадают. STRCMP(S, T) /* RETURN <0 IF S<T, 0 IF S==T, >0 IF S>T */CHAR S[], T[];{ INT I; I = 0; WHILE (S[I] == T[I]) IF (S[I++] == '\0') RETURN(0); RETURN(S[I]-T[I]);} Вот версия STRCMP с указателями: STRCMP(S, T) /* RETURN <0 IF S<T, 0 IF S==T, >0 IF S>T */CHAR *S, *T;{ FOR ( ; *S == *T; S++, T++) IF (*S == '\0') RETURN(0); RETURN(*S-*T);} так как ++ и -- могут быть как постфиксными, так ипрефиксными операциями, встречаются другие комбинации * и++ и --, хотя и менее часто. Например *++P увеличивает P до извлечения символа, на который указывает P, а *--P сначала уменьшает P. Упражнение 5-2 --------------- Напишите вариант с указателями функции STRCAT из главы2: STRCAT(S, T) копирует строку T в конец S. Упражнение 5-3 --------------- Напишите макрос для STRCPY. Упражнение 5-4 -------------- Перепишите подходящие программы из предыдущих глав и уп-ражнений, используя указатели вместо индексации массивов.Хорошие возможности для этого предоставляют функции GETLINE/главы 1 и 4/, ATOI, ITOA и их варианты /главы 2, 3 и 4/,REVERSE /глава 3/, INDEX и GETOP /глава 4/.