ПрограммированиеC разработчик

Как реализуется работа со строками в C? Объясните различие между массивом символов и указателем на строку. Как избежать ошибок работы со строками?

Проходите собеседования с ИИ помощником Hintsage

Ответ

В языке C строки реализованы как массивы символов, оканчивающиеся нулевым байтом ('\0'). Пример объявления строки:

char str1[] = "hello"; // Массив с 6 символами: {'h','e','l','l','o','\0'} char *str2 = "hello"; // Указатель на строковый литерал
  • Массив символов: Выделяет память под каждый элемент, включая завершающий ноль. Массив можно изменять (если он не const).
  • Указатель на строку: Может указывать на строковый литерал (который нельзя изменять), либо на выделенный участок памяти. Строковый литерал обычно размещается в read-only сегменте.

Чтобы избежать ошибок:

  • Правильно управляйте памятью (используйте malloc, strcpy, проверяйте размер буфера).
  • Для изменения строк не используйте строковые литералы.
  • Проверяйте, что все строки завершаются \0.

Пример корректной работы со строкой:

char buffer[100]; strcpy(buffer, "test"); // OK, buffer изменяемый и гарантированно содержит '\0'

Вопрос с подвохом

Какой результат выполнения следующего кода и к каким ошибкам он приведёт?

char *str = "hello"; str[0] = 'H'; printf("%s ", str);

Ответ: Программа приведёт к неопределённому поведению, скорее всего — сегфолту, потому что строковые литералы размещаются в области памяти только для чтения. Записывать значения по адресу строкового литерала нельзя.

Примеры реальных ошибок из-за незнания тонкостей темы


История Команда перепутала понятия массив строки и указатель на литерал. Одна функция принимала char *output = "default"; и далее выполняла strcpy(output, input);, что приводило к краху при первом же запуске, потому что копирование происходило в read-only память.


История При работе с сетью результат работы был записан в буфер, выделенный с помощью char *buf = NULL; strcpy(buf, data);. Это привело к записи в неинициализированную память и краху приложения.


История В пакете для локализации команда передавала строки между компонентами, не удостоверившись, что добавлен символ \0. Однажды функция вывела мусор в консоль и повредила внутреннюю структуру памяти.