Покажчики і символьні рядки
Строкова константа, написана у вигляді
являє собою масив символів. У внутрішньому представленні цей масив закінчується нульовим символом '\ 0'. за яким програма може знайти кінець рядка. Число зайнятих осередків пам'яті на одну більше, ніж кількість символів, поміщених між подвійними лапками.
Найчастіше рядкові константи використовуються як аргументи функцій, як, наприклад, в
Коли така символьний рядок з'являється в програмі, доступ до неї здійснюється через символьний покажчик; тобто printf отримує покажчик на початок масиву символів. Точніше, доступ до строкової константи здійснюється через покажчик на її перший елемент.
Строкові константи потрібні не тільки в якості аргументів функцій. Якщо, наприклад, змінну pmessage оголосити як
pmessage = "now is the time";
помістить в неї покажчик на символьний масив, при цьому сама рядок не копіюється, копіюється лише покажчик на неї. Операції для роботи з рядком як з єдиним цілим в Сі не передбачені.
Існує суттєва відмінність між наступними визначеннями:
char amessage [] = "now is the time"; / * Масив * /
char * pmessage = "now is the time"; / * Покажчик * /
amessage - це масив, що має такий розмір, що в ньому якраз поміщається зазначена послідовність символів і '\ 0'. Окремі символи всередині масиву можуть змінюватися, але amessage завжди вказує на одне і те ж місце пам'яті. На противагу йому pmessage є покажчик, ініціалізований так, щоб вказувати на строкову константу. Значення покажчика можна змінити, і тоді останній буде вказувати на що-небудь інше. Крім того, якщо ви спробуєте змінити вміст константи, результат буде невизначений.
Додаткові моменти, пов'язані з покажчиками і масивами, проілюструємо на кілька видозмінених варіантах двох корисних програм, взятих нами з стандартної бібліотеки. Перша з них, функція strcpy (s, t). копіює рядок t в рядок s. Хотілося б написати прямо s = t. але такий оператор копіює покажчик, а не символи. Щоб копіювати символи, нам потрібно організувати цикл. Перший варіант strcpy, з використанням масиву, має такий вигляд:
/ * Strcpy: копіює рядок t в s;
варіант з масивом * /
void strcpy (char s [], char t [])
while ((s [i] = t [i])! = '\ 0')
Для порівняння наведемо версію strcpy з покажчиками:
/ * Strcpy: копіює рядок t в s;
void strcpy (char * s, char * t)
Оскільки в функцію передаються лише копії значень аргументів, strcpy може вільно користуватися параметрами s і t як своїми локальними змінними. Вони належним чином ініціалізірованни покажчиками, які просуваються кожен раз на наступний символ в кожному з масивів до тих пір, поки в копируемой рядку t не зустрінеться '\ 0'.
На практиці strcpy так не пишуть. Досвідчений програміст віддасть перевагу більш коротку запис:
/ * Strcpy: копіює рядок t в s;
варіант 2 з покажчиками * /
void strcpy (char * s, char * t)
Приріст s і t тут здійснюється в керуючої частини циклу. Значним * t ++ є символ, на який вказує змінна t перед тим, як її значення буде збільшено; постфіксний оператор ++ не змінює покажчик t. поки не буде взятий символ, на який він вказує. Те ж саме щодо s. спочатку символ запам'ятається в позиції, на яку вказує старе значення s. і лише після цього значення змінної s збільшиться. Пересилається символ є одночасно і значенням, яке порівнюється з '\ 0'. В результаті копіюються всі символи, включаючи і заключний символ '\ 0'.
Помітивши, що порівняння з '\ 0' тут зайве (оскільки в Сі нульове значення виразу в умови трактується і як його істинність), ми можемо зробити ще одне і останнє скорочення тексту програми:
/ * Strcpy: копіює рядок t в s;
варіант 3 з покажчиками * /
void strcpy (char * s, char * t)
Хоча на перший погляд те, що ми отримали, виглядає загадково, все ж такий запис значно зручніше, і слід освоїти її, оскільки в програмах на Сі ви будете з нею часто зустрічатися.
Що стосується функції strcpy зі стандартної бібліотеки
Друга програма, яку ми тут розглянемо, це strcmp (s, t). Вона порівнює символи рядків s і t і повертає негативне, нульове або позитивне значення, якщо рядок s відповідно лексикографічно менше, дорівнює або більше, ніж рядок t. Результат виходить вирахуванням перших незбіжних символів з s і t.
/ * Strcmp: результат <0 при s > 0 при s> t * / int strcmp (char s [], char t []) for (i = 0; s [i] == t [i]; i ++)Схожі статті