Почему строки в C ++ обычно заканчиваются на «\ 0»?

Во многих примерах кода люди обычно используют '\0' после создания нового массива символов следующим образом:

 string s = "JustAString"; char* array = new char[s.size() + 1]; strncpy(array, s.c_str(), s.size()); array[s.size()] = '\0'; 

Почему мы должны использовать '\0' здесь?

Название вашего вопроса ссылается на строки C. C ++ std::string объекты обрабатываются иначе, чем стандартные строки C. \0 важно при использовании строк C, и когда я использую здесь термин string , я имею в виду стандартные строки C.

\0 действует как ограничитель строки в C. Он известен как нулевой символ или NUL . Он сигнализирует код, который обрабатывает строки – стандартные библиотеки, но также и ваш собственный код – где конец строки. Хорошим примером является strlen который возвращает длину строки.

Когда вы объявляете постоянную строку с:

 const char *str = "JustAString"; 

то автоматически добавляется \0 . В других случаях, когда вы будете управлять непостоянной строкой, как с вашим примером массива, вам иногда придется иметь дело с этим самостоятельно. Документы для strncpy , которые используются в вашем примере, являются хорошей иллюстрацией: strncpy копирует символы нулевого завершения, за исключением случаев, когда указанная длина достигнута до копирования всей строки. Следовательно, вы часто увидите strncpy сочетании с возможным избыточным назначением нулевого терминатора. strlcpy и strcpy_s были разработаны для решения потенциальных проблем, возникающих из-за пренебрежения обработкой этого случая.

В вашем конкретном примере array[s.size()] = '\0'; является одной из таких избыточности: поскольку array имеет размер s.size() + 1 , а strncpy копирует s.size() , функция добавит \0 .

Документация для стандартных служебных программ C укажет, когда вам нужно быть осторожным, чтобы включить такой нулевой терминатор. Но внимательно прочитайте документацию: как и с strncpy детали легко упускаются из виду, что приводит к потенциальному переполнению буфера.

Почему строки в C ++ обычно заканчиваются на '\0' ?

Обратите внимание, что строки C ++ и строки C не совпадают.
В C ++ строка относится к std :: string, которая является classом шаблона и предоставляет множество интуитивных функций для обработки строки.
Обратите внимание, что строка C ++ std :: string не завершается \0 , но class предоставляет функции для извлечения базовых строковых данных в виде строки c-style с завершением \0 .

В C строка – это набор символов. Эта коллекция обычно заканчивается символом \0 .
Если не используется специальный символ, такой как \0 не будет никакого способа узнать, когда закончится строка.
Он также точно известен как нулевой ограничитель строки.

Конечно, могут быть другие способы ведения бухгалтерского учета для отслеживания длины строки, но использование специального символа имеет два прямых преимущества:

  • Это более интуитивно понятное и
  • Нет дополнительных накладных расходов

Обратите внимание, что \0 необходимо, потому что большинство функций библиотеки Standard C работают с строками, предполагая, что они завершены \0 .
Например:
При использовании printf() если у вас есть строка, которая не завершена \0 printf() продолжает писать символы в stdout до тех пор, пока не встретится \0 , короче говоря, он может даже печатать мусор.

Почему мы должны использовать '\0' здесь?

Существует два сценария, когда вам не нужно \0 завершать строку:

  • При любом использовании, если вы явно заполняете длину строки и
  • Если вы используете некоторую стандартную библиотеку, api будет неявно добавлять строки \0 в строки.

В вашем случае у вас уже есть второй сценарий для вас.

 array[s.size()] = '\0'; 

Вышеприведенный оператор кода лишний в вашем примере.

Для вашего примера использование strncpy() делает его бесполезным. strncpy() копирует s.size() символы в ваш array , Обратите внимание, что он добавляет нулевое завершение, если после копирования строк осталось какое-то место. Поскольку array имеет размер s.size() + 1 a \0 , автоматически добавляется.

‘\ 0’ является символом нулевого завершения. Если в вашем массиве символов его нет, и вы попытались выполнить команду strcpy, у вас будет переполнение буфера. Многие функции полагаются на него, чтобы знать, когда им нужно прекратить чтение или запись памяти.

 strncpy(array, s.c_str(), s.size()); array[s.size()] = '\0'; 

Почему мы должны использовать ‘\ 0’ здесь?

Вы не должны, чтобы вторая строка была пустой тратой пространства. strncpy уже добавляет нулевое завершение, если вы знаете, как его использовать. Код можно переписать как:

 strncpy(array, s.c_str(), s.size()+1); 

strncpy – это какая-то странная функция, она предполагает, что первый параметр представляет собой массив размера третьего параметра. Таким образом, он копирует только нулевое завершение, если после копирования строк осталось какое-то место.

Вы также могли бы использовать memcpy () в этом случае, он будет немного более эффективным, хотя, возможно, делает код менее понятным для чтения.

В C мы представляем строку с массивом char (или w_char) и используем специальный символ для обозначения конца строки. В отличие от Pascal, который хранит длину строки в индексе 0 массива (таким образом, строка имеет жесткий предел количества символов), теоретически нет ограничений на количество символов, которые строка (представлена ​​как массив символов) может иметь значение C.

Ожидается, что специальный символ будет иметь NUL во всех функциях из библиотеки по умолчанию в C, а также в других библиотеках. Если вы хотите использовать библиотечные функции, которые полагаются на точную длину строки, вы должны прервать строку с помощью NUL. Вы можете полностью определить свой собственный завершающий символ, но вы должны понимать, что функции библиотеки, содержащие строку (как массив символов), могут работать не так, как вы ожидаете, и это вызовет всевозможные ошибки.

В приведенном fragmentе кода необходимо явно указать конечный символ на NUL, так как вы не знаете, есть ли данные мусора в выделенном массиве. Это также хорошая практика, поскольку в большом коде вы можете не видеть инициализацию массива символов.

  • Каков наилучший способ извлечения первого слова из строки в Java?
  • Java: разделение запятой строки, но игнорирование запятых в кавычках
  • Как найти и заменить строку?
  • Многострочная строка с дополнительным пространством (сохраненный отступ)
  • Как удалить символ по заданному индексу из строки в C?
  • Как превратить формулу строки в «реальную» формулу
  • Преобразование строкового представления списка в список
  • Как отформатировать строку в качестве номера телефона в C #
  • Строки Java: «String s = новая строка (« глупо »);
  • Что такое пул строк Java и как он отличается от нового String («s»)?
  • Android: что-то лучше, чем андроид: ellipsize = "end", чтобы добавить "..." в укороченные длинные строки?
  • Давайте будем гением компьютера.