Чи всі рядки можна вважати масивом символів ( Так ), чи всі масиви символів можна вважати рядками ( Ні ).
Чому ні? і чому це важливо?
На додаток до інших відповідей, що пояснюють, що довжина рядка ніде не зберігається як частина рядка та посилання на стандарт, де визначена рядок, зворотний бік - "Як функції бібліотеки C обробляють рядки?"
Хоча масив символів може містити однакові символи, це просто масив символів, якщо за останнім символом не супроводжується символом, що закінчується нульовим завершенням . Цей нульовий символ - це те, що дозволяє масиву символів вважати рядком.
Усі функції в C, які очікують рядок як аргумент, очікують, що послідовність символів буде скасована на нуль . Чому?
Це пов'язано з тим, як працюють всі рядкові функції. Оскільки довжина не включена як частина масиву, рядкові функції сканують в масив вперед, поки не буде знайдено нульовий символ (наприклад '\0'
- еквівалент десятковому 0
). Див. Таблицю та опис ASCII . Незалежно від того, чи використовуєте ви strcpy
, strchr
, strcspn
і т.д .. Все рядкові функції покладаються на NUL кінцевого характеру присутнім визначити , де кінець цього рядка є.
Порівняння двох подібних функцій від string.h
підкреслить важливість нульового припинення характеру. Візьмемо для прикладу:
char *strcpy(char *dest, const char *src);
strcpy
Функція просто копіює байти з src
до dest
до NUL кінцевого символ, не знайдено розповідаючи , strcpy
де зупинити копіювання символів. Тепер візьміть аналогічну функцію memcpy
:
void *memcpy(void *dest, const void *src, size_t n);
Функція виконує аналогічну операцію, але не враховує і не вимагає, щоб src
параметр був рядком. Оскільки memcpy
не можна просто сканувати вперед при src
копіюванні байтів до dest
тих пір, поки не буде досягнуто символу, що закінчує нуль, для копіювання в якості третього параметра потрібно явне число байтів. Цей третій параметр забезпечує memcpy
однаковий розмір інформації, strcpy
який можна отримати просто шляхом сканування вперед, поки не буде знайдено нульовий символ.
(що також підкреслює, що йде не так strcpy
(або будь-яка функція, що очікує рядок), якщо ви не в змозі надати функцію з нульовим завершенням рядка - вона не має уявлення, де зупинитися, і з радістю побіжить за рештою вашого сегмента пам'яті виклик не визначеної поведінки, поки нульовий символ просто не знайдеться десь у пам'яті - або не станеться помилка сегментації)
Ось чому функції, які очікують нуль-закінченого рядка, повинні передаватися нульовим завершеним рядком і чому це має значення .
char str[] = "hello";
випадок.