Почему строки в C должны заканчиваться нулем? - PullRequest
19 голосов
/ 08 февраля 2010

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

Языки, такие как PHP, автоматически обнуляют строки, когда они интерпретируются и / или анализируются?

Ответы [ 9 ]

28 голосов
/ 08 февраля 2010

От Отличная статья Джоэла на тему:

Помните, как строки работают в C: они состоят из группы байтов, за которыми следует нулевой символ, значение которого равно 0. Это имеет два очевидных значения:

Нет способа узнать, где заканчивается строка (то есть длина строки), не перемещаясь по ней, ища нулевой символ в конце. В вашей строке не должно быть нулей. Таким образом, вы не можете хранить произвольный двоичный объект типа картинки JPEG в строке C. Почему C-строки работают таким образом? Это связано с тем, что микропроцессор PDP-7, на котором были изобретены UNIX и язык программирования C, имел строковый тип ASCIZ. ASCIZ означает «ASCII с Z (ноль) в конце».

Это единственный способ хранить строки? Нет, на самом деле, это один из худших способов хранения строк. Для нетривиальных программ, API, операционных систем, библиотек классов следует избегать строк ASCIZ, таких как чума.

7 голосов
/ 08 февраля 2010

Строки C - это массивы символов, а массив C - это просто указатель на область памяти, которая является start расположением массива. Но также длина (или конец) массива должна быть выражена как-то; в случае строк используется нулевое завершение. Другой альтернативой было бы как-то перенести длину строки вместе с указателем памяти, или поместить длину в первую позицию массива, или что-то еще. Это просто вопрос соглашения.

Языки более высокого уровня, такие как Java или PHP, сохраняют информацию о размере вместе с массивом автоматически и прозрачно, поэтому пользователю не нужно беспокоиться о них.

5 голосов
/ 08 февраля 2010

C не имеет понятия о строках. Строки являются просто массивами символов (или wchars для Unicode и т. Д.).

Из-за этих фактов C не может проверить, то есть длину строки, так как нет «mystring-> length», где-то не задано значение длины. Единственный способ найти конец строки - это перебрать ее и проверить наличие \ 0.

Существуют строковые библиотеки для C, которые используют такие структуры, как

struct string {
    int length;
    char *data;
};

для устранения необходимости завершения \ 0, но это не стандартная C.

Языки, такие как C ++, PHP, Perl и т. Д., Имеют свои собственные внутренние библиотеки строк, которые часто имеют отдельное поле длины, которое ускоряет некоторые строковые функции и устраняет необходимость в \ 0.

Некоторые другие языки (например, Pascal) используют строковый тип, который называется (удивительно) Pascal String, он хранит длину в первом байте строки, что является причиной того, что длина этих строк ограничена 255 символами.

4 голосов
/ 26 мая 2013

Подумайте, что такое память: непрерывный блок единиц байтового размера, который может быть заполнен любыми битовыми комбинациями.

2a c6 90 f6

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

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

Пример

Давайте посмотрим на эту строку в памяти ...

H e l l o , w o r l d ! \0 
^
|
+------ Pointer to string

... мы видим, что строка логически заканчивается после символа !. Если бы не было \0 (или какого-либо другого метода определения его конца), как бы мы узнали, ища в памяти, что мы закончили с этой строкой? Другие языки содержат длину строки с типом string , чтобы решить эту проблему.

Я задал этот вопрос, когда мои базовые знания о компьютерах были ограничены, и этот - это ответ, который помог бы много лет назад. Я надеюсь, что это помогает кому-то еще. :)

4 голосов
/ 08 февраля 2010

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

В указателе нет места для хранения длины, поэтому вам нужно указать, где находится конец строки.

В Си было решено, что это будет обозначено нулевым символом.

Например, в паскале длина строки записывается в байте, непосредственно предшествующем указателю, поэтому максимальная длина строки паскаля составляет 255 символов.

1 голос
/ 08 февраля 2010

В C-строках представлены массивом символов, размещенных в непрерывном блоке памяти, и, таким образом, должен быть либо индикатор, указывающий конец блока (т. Е. Нулевой символ), либо способ хранения длины ( как строки Паскаля с префиксом длины).

В таких языках, как PHP, Perl, C # и т. Д. Строки могут иметь или не иметь сложные структуры данных, поэтому нельзя предполагать, что они имеют нулевой символ. В качестве надуманного примера у вас может быть язык, представляющий строку наподобие:

class string
{
   int length;
   char[] data;
}

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

1 голос
/ 08 февраля 2010

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

Языки более высокого уровня, такие как PHP, могут скрывать нулевое завершение от вас или не использовать его вообще - например, они могут поддерживать длину. C не делает это таким образом из-за накладных расходов. Языки высокого уровня могут также не реализовывать строки в виде массива char - они могут (и некоторые делают) реализовывать их, например, в виде списков массивов char.

1 голос
/ 08 февраля 2010

Это соглашение - его можно было бы реализовать с помощью другого алгоритма (например, длина в начале буфера).

На языке «низкого уровня», таком как ассемблер, легко эффективно проверить на «NULL»: это может упростить решение использовать строки с концевыми NULL вместо отслеживания счетчика длины.

0 голосов
/ 08 февраля 2010

Они имеют нулевое окончание, потому что все функции Стандартной библиотеки ожидают их.

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