Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

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

const char *str = "JustAString";

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

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

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

Ответ 2

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

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

В 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, автоматически добавляется.

Ответ 3

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

Ответ 4

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

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

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

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

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

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

Ответ 5

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

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

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