Что значит быть "законченным нулем"?

Я попадаю на C/С++, и многие термины появляются не знакомы мне. Одна из них - это переменная или указатель, которая заканчивается нулем. Что означает, что пространство в памяти должно быть завершено нулем?

Ответ 1

Возьмите строку Hi в ASCII. Его простейшим представлением в памяти является два байта:

0x48
0x69

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

Итак, C имеет стандарт, в котором строки заканчиваются нулевым байтом, также известным как символ NUL:

0x48
0x69
0x00

Теперь строка имеет недвусмысленно два символа, потому что перед NUL есть два символа.

Ответ 2

Это зарезервированное значение, указывающее конец последовательности (например) символов в строке.

Более корректно известен как null (или NUL) завершен. Это связано с тем, что используемое значение равно нулю, а не как код символа для "0". Чтобы прояснить различие, проверьте таблицу набор символов ASCII.

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

Обратите внимание, что существует различие между длиной строки и длиной массива char, который был первоначально объявлен.

char name[50];

Объявляет массив из 50 символов. Однако эти значения будут неинициализированы. Поэтому, если я хочу сохранить строку "Hello" (длиной 5 символов), я действительно не хочу беспокоить установку оставшихся 45 символов пробелами (или некоторым другим значением). Вместо этого я сохраняю значение NUL после последнего символа в моей строке.

Более поздние языки, такие как Pascal, Java и С#, имеют определенный тип string. Они имеют значение заголовка, указывающее количество символов в строке. Это имеет несколько преимуществ; во-первых, вам не нужно идти до конца строки, чтобы узнать ее длину, во-вторых, ваша строка может содержать нулевые символы.

Википедия имеет дополнительную информацию в String (computer science).

Ответ 3

Заканчивается нулем

Это, когда ваш заостренный начальник борется с вами.

Ответ 4

Массивы и строка в C - это просто указатели на ячейку памяти. По указателю вы можете найти начало массива. Конец массива undefined. Конец массива символов (который является строкой) равен нулю.

Итак, в строке памяти hello написано как:

68 65 6c 6c 6f 00                                 |hello|

Ответ 5

Это относится к тому, как строки C хранятся в памяти. Символ NUL, обозначенный символом \0 в символах строки, присутствует в конце строки C в памяти. Других метаданных, связанных, например, с строкой типа C, например, длиной, нет. Обратите внимание на различную орфографию между символом NUL и указателем NULL.

Ответ 6

Строки в стиле C заканчиваются символом NUL ('\ 0'). Это обеспечивает маркер для функций, которые работают со строками (например, strlen, strcpy), чтобы использовать для идентификации конца строки.

Ответ 7

Существует два распространенных способа обработки массивов, которые могут иметь различную длину (например, строки). Первый заключается в том, чтобы отдельно хранить длину данных, хранящихся в массиве. Такие языки, как Fortran и Ada и С++ std::string, делают это. Недостатком этого является то, что вы каким-то образом должны передать эту дополнительную информацию всему, что связано с вашим массивом.

Другой способ - зарезервировать дополнительный элемент не-данных в конце массива, который будет служить в качестве часового. Для дозорника вы используете значение, которое никогда не должно появляться в фактических данных. Для строк 0 (или "NUL" ) является хорошим выбором, поскольку это непечатаемо и не служит никакой другой цели в ASCII. Итак, что C (и многие языки, скопированные из C), это предположить, что все строки заканчиваются (или "завершаются" ) 0.

Есть несколько недостатков. Во-первых, это медленно. Каждый раз, когда процедура должна знать длину строки, это операция O (n) (поиск по всей строке, которая ищет 0). Другая проблема заключается в том, что вы когда-нибудь захотите поместить 0 в свою строку по какой-то причине, так что теперь вам нужен целый второй набор строковых подпрограмм, которые игнорируют нуль и в любом случае используют отдельную длину (например: strnlen()). Третья большая проблема заключается в том, что если кто-то забывает положить это 0 в конце (или он каким-то образом уничтожен), следующая операция строки, чтобы выполнить проверку на десятую, будет весело маршировать через память, пока она не случайно случайно не найдет другой 0, сбоев, или пользователь теряет терпение и убивает его. Такие ошибки могут быть серьезными PITA для отслеживания.

По всем этим причинам подход C обычно рассматривается с немилостью.

Ответ 8

В то время как классический пример "завершается нулем" - это значение строк в C, понятие более общее. Он может быть применен к любому списку вещей, хранящихся в массиве, размер которого неизвестен явно.

Трюк состоит в том, чтобы избежать пропускания размера массива, добавив значение дозорного элемента в конец массива. Как правило, используется некоторая форма нуля, но она может быть чем угодно (например, NAN, если массив содержит значения с плавающей запятой).

Вот три примера этого понятия:

  • C строк, конечно. К строке добавляется один нулевой символ: "Hello" кодируется как 48 65 6c 6c 6f 00.

  • Массивы указателей, естественно, допускают нулевое завершение, потому что нулевой указатель (тот, который указывает на нулевой адрес) определен так, чтобы никогда не указывать на действительный объект. Таким образом, вы можете найти такой код:

    Foo list[] = { somePointer, anotherPointer, NULL };
    bar(list);
    

    вместо

    Foo list[] = { somePointer, anotherPointer };
    bar(sizeof(list)/sizeof(*list), list);
    

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

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

    Foo list[] = {
        { someValue, somePointer },
        { anotherValue, anotherPointer },
        { 0, NULL }
    };
    bar(list);
    

    или даже

    Foo list[] = {
        { someValue, somePointer },
        { anotherValue, anotherPointer },
        {}    //C zeros out an object initialized with an empty initializer list.
    };
    bar(list);