Почему строки в C должны оканчиваться нулем?

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

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


person alex    schedule 08.02.2010    source источник
comment
Связанные или, возможно, повторяющиеся: stackoverflow.com/questions/1253291/   -  person    schedule 08.02.2010
comment
Только что нашел это: stackoverflow.com/questions / 2037209 /   -  person alex    schedule 08.02.2010
comment
Существует два распространенных метода представления текста: 1. Указание длины с последующим текстом. Или используя завершающий символ. Многие базы данных используют первое. Один вопрос, который стоит задать себе: как определяется конец строки?   -  person Thomas Matthews    schedule 09.02.2010


Ответы (9)


Из отличной статьи Джоэла по этой теме:

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

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

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

person Max Shawabkeh    schedule 08.02.2010
comment
отлично, спасибо ... и какие еще методы это могут быть? Спасибо. - person Joe DF; 06.06.2013
comment
Есть ли в C99 стандартный способ создания строки, отличной от ASCIZ? - person Arc676; 19.10.2015

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

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

person Joonas Pulakka    schedule 08.02.2010

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

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

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

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

person PaulJWilliams    schedule 08.02.2010

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

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

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

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

чтобы убрать необходимость в \ 0-завершении, но это не стандарт C.

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

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

person Morfildur    schedule 08.02.2010

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

2a c6 90 f6

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

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

Пример

Посмотрим на эту строку в памяти ...

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

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

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

person alex    schedule 25.05.2013

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

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

person jldupont    schedule 08.02.2010

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

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

person Community    schedule 08.02.2010

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

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

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

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

person Vishal Mistry    schedule 08.02.2010

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

person Alexander Poluektov    schedule 08.02.2010
comment
А также потому, что в спецификации языка C указано, что строковые литералы кодируются. - person Stephen C; 08.02.2010
comment
@Stephen C, ты единственный, кто это сказал! Очень важная причина! Глупые строки C ... Я бы хотел C, libc и строковые литералы со строками паскаля. - person Prof. Falken; 04.11.2010