Завершающий NULL в массиве в C - PullRequest
3 голосов
/ 27 декабря 2010

У меня простой вопрос.Почему необходимо учитывать завершающий ноль в массиве символов (или просто в строке), а не в массиве целых чисел.Поэтому, когда я хочу, чтобы строка содержала 20 символов, мне нужно объявить char string[21];.Когда я хочу объявить массив целых чисел, содержащий 5 цифр, тогда достаточно int digits[5];.В чем причина?

Ответы [ 9 ]

7 голосов
/ 27 декабря 2010

Вам не нужно завершать массив char с помощью NULL, если вы этого не хотите, но когда вы используете их для представления строки, вам нужно это сделать, поскольку C использует null завершенные строки для представления его строк. Когда вы используете функции, которые работают со строками (например, strlen для длины строки или printf для вывода строки), эти функции будут считывать данные до тех пор, пока не встретится NULL. Если его нет, вы, скорее всего, столкнетесь с переполнением буфера или аналогичными проблемами нарушения доступа / сегментации.

Вкратце: так C представляет строковые данные.

4 голосов
/ 27 декабря 2010

Нулевые терминаторы требуются в конце строк (или символьных массивов), потому что:

  1. Большинство стандартных строковых функций библиотеки ожидают наличия нулевого символа.Это вместо передачи явной длины строки (хотя некоторые функции требуют этого вместо этого.)
  2. По своей конструкции символ NUL (ASCII 0x00) используется для обозначения конца строки.Следовательно, почему он также используется как символ EOF при чтении из файлов или потоков ASCII.

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

3 голосов
/ 27 декабря 2010

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

3 голосов
/ 27 декабря 2010

Речь идет не о том, чтобы объявить массив, который на единицу больше, а о том, как мы решаем определять строки в C.

По условию строки C считаются последовательностью символов, оканчивающихся окончательным символом NUL, Как Вам известно.Он запекается в языке в форме интерпретации "string literals" и принимается всеми стандартными библиотечными функциями, такими как strcpy и printf и т. Д. Все согласны с тем, что именно так мы будем делать строки в C, иэтот символ должен сообщать тем функциям, где заканчивается строка.

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

3 голосов
/ 27 декабря 2010

Только условно, что строки C заканчиваются символом ascii nul.(На самом деле это нечто иное, чем NULL.)

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

Итак, ответ таков: все массивы должны выделять место для всех своих элементов.Ваша "строка из 20 символов" - это просто строка из 21 символа, включая нуль-байт.

3 голосов
/ 27 декабря 2010

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

Итак, когда вы используете printf с символом формата %s, это по существуделает это:

int i = 0;
while(input[i] != '\0') {
   output(input[i]);
   i++;
}

Эта концепция широко известна как дозорный .

2 голосов
/ 27 декабря 2010

Не обязательно, чтобы массив символов состоял из 21 элемента.Это необходимо, только если вы следуете (почти всегда предполагаемому) соглашению, что за двадцатью символами следует нулевой терминатор.Обычно нет такого соглашения для терминатора в целых и других массивах.

1 голос
/ 02 января 2011

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

Точно так же, как я должен привести вашу дочь домой в полночь, если я хочу с ней встречаться - просто соглашение с библиотекой(или в этом случае отец).

1 голос
/ 27 декабря 2010

Из-за технических причин того, как C Строки реализованы по сравнению с другими соглашениями

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...