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

Почему C не завершает строки со специальным экранированным символом окончания строки?

В C строки завершаются нулем (\ 0), что вызывает проблемы, когда вы хотите поместить нуль в строки. Почему бы не создать специальный экранированный символ, например\$или что-то?

Я полностью понимаю, насколько глупый этот вопрос, но мне было любопытно.

4b9b3361

Ответ 1

Завершение с помощью 0 имеет много особенностей производительности, которые были очень важны в конце 60-х годов.

У процессоров есть инструкции для условного перехода на тест на 0. На самом деле, некоторые процессоры даже имеют инструкции, которые будут перебирать/копировать последовательность байтов до 0.

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

Теперь другие языки (кашель, паскаль, кашель) используют строки в стиле count/value. Для них любой символ действителен, но они всегда содержат счетчик с размером строки. Преимущество очевидно, но есть и недостатки этой техники.

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

Edit:

Я не думаю, что вопрос немой. В эти дни языков высокого уровня с управлением памятью, невероятной мощностью процессора и неприличным объемом памяти такие решения из прошлого вполне могут казаться бессмысленными. И, действительно, они МОГУТ быть бессмысленными в наши дни, поэтому им будет интересно расспросить их.

Ответ 2

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

Если вы использовали \$ для завершения строк, какое значение байта оно имело бы в памяти? Как бы вы включили это значение байта в строку?

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

Ответ 3

Я думаю, потому что это быстрее проверять и совершенно невероятно происходить в разумной строке. Кроме того, помните, что C не имеет понятия строк. Строка в C не является чем-то само собой. Это просто массив символов. Тот факт, что он назывался и использовался как строка, является чисто случайным и условным.

Ответ 4

Это вызывает проблемы, но вы можете вставлять \0...

const char* hello = "Hello\0World\0\0";

Это вызывает проблему, если передать это стандартным библиотечным функциям, например strlen, но не иначе.

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

const char* hello = "\x0BHello World";

... как это делают некоторые другие языки.

Ответ 5

Если стандартные функции библиотеки, такие как strlen или printf, могут (по выбору) искать маркер конца строки \777 (в качестве альтернативы \000), вы можете иметь постоянную строку символов, содержащую \0s:

const char* hello = "Hello\0World\0\0\777"; 
printf("%s\n", hello); 

Кстати, если вы хотите отправить a\0 в stdout (aka -print0), вы можете использовать:

putchar(0); 

Ответ 6

То же по историческим причинам.

Создатели std::string в С++ распознали этот недостаток, поэтому std::string может содержать нулевой символ. (Но будьте осторожны построение std::string с нулевым символом!)

Если вы хотите иметь C-строку (точнее, квази-C-строку) с нулевым символом, вам нужно будет сделать свою собственную структуру.

typedef struct {
    size_t length;
    char[] data; //C99 introduced the flexible array member
} my_string;

Или вам придется отслеживать длину строки каким-либо другим способом и передавать ее каждой строковой функции, которую вы пишете.

Ответ 7

Не для некрополя, преднамеренно, но это все еще очень важно для встроенного SQL.

Если вы имеете дело с двоичными данными на C, вы должны создать двоичный объект в структуре данных. Если вы можете себе это позволить, достаточно массива char. Это, вероятно, не строка, не так ли?

Для значений хэша/дайджеста, их обычно "HEX" выходят в члены {'0',.., 'F'}. Затем они могут быть "UNHEXED" во время операции с базой данных.

Для операций с файлами рассмотрите двоичный поток с логической длиной записи.

Выход из них сам по себе действительно безопасен, если вы можете гарантировать кодирование. На самом деле это можно увидеть в разгрузке MYSQLDUMP (SQL), где двоичные файлы правильно экранированы для UTF-8, и схема установки "нажимается" для загрузки и "выталкивается" впоследствии.

Я не сторонник использования вызова dbms для того, что должно быть библиотечной функцией, но я видел это. (выберите real_escape_string ($ string)).

И там base64, что является еще одной возможностью червей. Google UUENCODE.

Итак, да, функция mem *, если ваши символы имеют фиксированную ширину.

Ответ 8

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

Чтобы немного перефразировать вопрос Майкла, как бы вы ожидали "Hello\0World\0"?