В памяти такая строка занимает те же что и С = число символов в строке + 1 байт в начале, хранящий её длину.
1. С помощью указателя можно гулять по ЛЮБОЙ строке.
2. Зачем вам на практике 4204067..... ? Если речь идет о текстовом редакторе, то там совсем по другому организовано хранение. Не в одной строке.
3. Разве что в примитивных текстовых редакторах можно все запихнуть в одну строку.
4. Если тебе нужно работать со строками такой длины 4204067..., то для строки типа Паскаль никто не мешает использовать не 1 (ограничение на максимальную длину 255), а 4 байта для хранения длины.
5. Что? В строка типа Паскаль можно хранить на 3 полезных байта меньше? При длине строки 4204067... ты считаешь это важным?
А если действительно используются возможности по максимуму, то есть работаем с гигантскими строками 4204067..., то искать конец строки в такой строке - просто глупо.
Да я могу хоть каталог файлов так сохранить один за другим. Маркерная система - это обычная система, которую придумали ещё до C. В данном случае маркер конца данных - нуль-символ. У тебя нет таких навыков, поэтому все мысли только через размер данных идут.
Конечно, проходить по всей строке с проверками на нуль-символ, - способ неправильный. Зато можно работать с данными напрямую, без заморочек с размером.
Можно нарезать их прямо с середины. В любом месте можно встать и поставить начало внутренней строки (подстроки). Вот там есть пример в библиотеке - strtok() - когда строку можно нарезать на слова, сохраняя указатели на них. Можно и интереснее операции делать - ограничений нет. С размером этой возможности нет, там всё тупо и ограничено.
Зато можно работать с данными напрямую, без заморочек с размером. Можно нарезать их прямо с середины. В любом месте можно встать и поставить начало внутренней строки (подстроки).
Вот там есть пример в библиотеке - strtok() - когда строку можно нарезать на слова, сохраняя указатели на них. Можно и интереснее операции делать - ограничений нет. С размером этой возможности нет, там всё тупо и ограничено.
0 в конце подразумевает линейный перебор в поисках конца.
В БД и файловой системы индексы используются, иначе они работают неприемлимо долго.
А при наличие индекса ноль в конце уже не нужен.
Все эти вещи давно уже в библиотеках да в компилятор встроены.
А как ты там файлы искать будешь?
В таких случаях используют каталог вложенных файлов, а где каталог - там и размеры.
Нельзя.
При выполнении операции, нужно быть уверенным, что ты не выходишь за пределы выделенной под строку памяти.
Как раз наборот, дурачок.
При разрезании строки твоим методом вставки нуля в середину - нужно СДВИГАТЬ всю последующую часть строки на один байт.
А вот наличие отдельной структуры, хранящей длины виртуально нарезанных строк позволяет разрезать строки без массовых ненужных перемещений в памяти.
4. Самый быстрый метод разрезания строк (без сдвигов) - гигантская (без 0) строка. И отдельный каталог, содержащий определения (адреса и размеры) виртуально порезанных подстрок.
Методом добавления 0 разрезать строку на подстроки, сохраняя указатели на них, невозможно.
То есть, по-твоему, кто сделал такие строки, - это просто дебилы. Один ты умник.
Да, оно подразумевает линейный перебор, и все это знают и всегда знали.
Речь про хранение идёт. Ты предлагаешь хранить длину рядом с каждой строкой, потому что другого варианта нет.
То есть к индексами добавляется и длина эта.
Или ты ещё пуще пошёл и длину сохранил в индекс, чтобы ещё веселее было.
Да, походу, так и есть, ты предлагаешь индексировать на пустом месте. То есть жрать память попусту.
Какие вещи? Определение длины строки?
Там же маркер в конце, забыл? Дурилка ты картонная.
Что ты хочешь сказать, что я не могу для строки правильно выделить память до сохранения?
Епать, а strtok() что делает? Значит, ты просто не знаешь, как работает strtok(), раз такую ахинею пронёс.
Строка меняется, цель - получить подстроку
Позволяет, конечно, но нахрен нужны эти размеры в памяти? При нарезке на подстроки нужно просто расставить маркеры, а длина всего массива известна заранее. Потом эти подстроки ещё можно нарезать, никаких длин не надо знать.
В C делаешь структуру (указатель, длина), если нужно исходную строку сохранить. Если же это нафиг не надо, то просто нарезаешь её без всяких структур и заморочек с ними. А сдвиги, ну это ты сам придумал себе и героически победил у себя в голове.
Ну да, я понял, что ты пропёрся из-за своего тупого паскалевского мышления. Не в том смысле, что ты тупой, а в том, что Паскаль притупляет мышление и у паскалистов всё сводится к одному способу всегда, потому что язык большего не позволяет. В C же гибкость - обычное дело. Ты можешь и хранить длину, и не хранить длину.
То есть ты даже НЕ ПОНИМАЕШЬ, что твой алгоритм нарезания строк вставкой 0 в середину подразумевает 2 операции, существенно снижающих производительность:
Приведи здесь пример своего кода, реализующего твой "эффективный простой безсдвиговый" алгоритм:
Если ты проводишь над КОПИЕЙ то где твоя хваленая эффективность.
Командная строка уже много лет как прекрасно нарезается готовыми библиотеками
Твои примеры на уровне задачек по программированию для школьников или студентов
В том же примере касаемо сети ты просто никогда не писал сетевых программ, иначе хорошо бы представлял протоколы, в которые паскалевские строки никак не вписываютс
Во-первых, это может быть непереносимо - когда для одной платформы есть библиотека, а для другой нет. А во-вторых, когда нужен свой способ обработки командной строки, отличающийся от общепринятых, то существующие реализации в этом не помогут. Но при этом по аргументам надо пройти не более одного раза
Напоминаю исходные нашей беседы: твой довод, что "миллиард нуль-терминированных строк длинной миллиард символов эффективнее строк, чей размер хранится".
Функция обрабатывающая строки непереносима между платформами?
Ты дурак?
именно я рассказал тебе, что паскалевские строки неудобны в протоколах междупрограммного обмена
Функций для обработки параметров командной строки напридумано достаточно много, чтобы найти среди них готовую.
Ну, я ж говорю, ты тупой. Есть непереносимые библиотеки. А функции - в библиотеках. Если программа линкуется с библиотекой, которой нет в другой операционной системе, это как называется? Речь же идёт о функциях разбора аргументов командной строки. Ты съехал просто, подменив их функциями для работы с любыми строками.
Конечно эффективнее, при хранении это экономит 4 гигабайта. При чтении разница только в проверках. А что больше времени происходит, хранение или чтение? Естественно, хранение.
А на коротких строках, пример - "hello", нуль-терминированные эффективнее размерных, потому что размер не нужен вообще.
Ну, вот в Go придумали свои, я тут Олежку пердуна валил, дал ему задание, он свинтил. Понтов было выше крыши. А почему? Потому что они нарушили POSIX и сказали "а вы просто нас не понимаете, это такая продвинутая реализация". Потому и надо там писать свой разборщик, хотя в библиотеке, поставляемой с компилятором, есть это их новаторское средство.
3. Пакет "flag" не обязателен, господин школьник. Параметры командной строки в C-подобном стиле берутся из os.Args
2. Зачем? Ты как-то хотел использовать какую-то С-библиотеку для разбора параметров командной строки в Go? Но не знаешь как?
1. Ты о чем? Это же другой язык программирования.
4. А каким боком здесь про 0-терминированные строки? В Go встроенные строки - паскалеподобного типа.
А зачем тогда этот пакет нужен? Он нарушает POSIX, который вырабатывался десятилетиями. И нарушает его, естественно, в далеко не лучшую сторону. Люди придумали нормальную, гибкую систему, эти взяли, своё что-то выдумали за пять минут, а потом лепят отмазки, что их просто не понимают.
То есть наличие какой-то библиотеки ещё ни о чём не говорит, хоть их сотни.
Ты в этом не разбираешься, потому что не пишешь ничего.
Не соблюдает он POSIX, ты знаешь, что такое POSIX? Очень сомневаюсь.
Держу пари, ты сейчас с винды мне всё это пишешь.
У тебя мозгов не хватает объединить сообщения в одно. Так что это либо телефон, либо винда. На телефон у тебя денег нет (с преподской зарплатой такой возможности нет), остаётся одно.
Другой, конечно. Но речь о библиотеках, а в нём они есть. При этом он современный, а не 20-летней давности.
Для тебя - если библиотека есть, то ею можно пользоваться. Так вот, это - теория. Большинство библиотек непригодно к использованию, а ясно это становится, когда начинаешь ими пользоваться. Для тебя же они все одинаковые, потому что ты не пользовался ими.
В Go строки вообще в виде структур вида (указатель, длина). То есть они там вообще высокоуровневые.
Да они и не заморачивались с производительностью, вообще много с чем там не заморачивались. Вот сейчас споры идут по поводу его качества.
Речь идёт о том, как оптимальнее использовать строки: по-паскалевски или по-сишному. Паскалевский вариант жрёт память, к тому же устаревает, так как размеры растут со временем, а в нём остаются старые размеры. А сишный вариант как был компактным, так и остался, даже с юникодом.
Go предлагает 2 варианта - в новом стиле и в старом, выбирай любой.
Чего ради Go должен соблюдать POSIX для C?
Если вы не способны разобраться даже в стандартной библиотеке
Go соблюдает POSIX ровно настолько насколько авторы языка сочли нужным.
Именно это и означает паскалеподобные строки.
А он мне приносит 5000-7000 долларов ежемесячно.
Это никому не надо, кроме как во встраиваемых устройствах
строке на миллиард символов достаточно 4 байт для записи размера
если мало, можно взять 8
зато, чтобы вычислить длину строки - надо пройти её от начала и до конца
Хорошее чтиво:
Дельфи программы тормозят
Кто хранит строки миллиардного размера в C-string literals?
А теперь представь строку на миллиард символов. Для такой строки затраты на хранение её длины остаются теми же - один байт в котором записан нуль-символ.
А вот если бы длина строки хранилась в переменной, то нужно было бы следить за размером этой переменной, потому что на слишком длинных строках числовое значение длины не помещалось бы в переменную.
Ты думаешь, почему Дельфи такой медленный язык (программа The Bat! работает медленно), потому что там этого нет, из-за чего происходит множество лишних вычислений.
Ну, а теперь представь миллиард строк по миллиарду символов, где для каждой строки нужно не только место под размер занимать, но и выполнять операции по вычислению размера.
Они не только тормозят, но и весят слишком много. Это не из-за оптимизаций, а потому что он спроектирован так, чтобы особо не заморачиваться в плане ресурсов окружения.
Да можешь отдельно себе сделать структуру без всякого нуль-символа и хранить там всё.
Но когда ты через printf() или cout<< выводишь "hello", то слишком жирно для этого hello выделять 8 байт.
тот же std::string вполне себе хранит размер
Ну этот же size_t и поместите в качестве первого байта. Почему вы не говорите, что возвращаемый strlen результат "слишком большой"?
А для строки типа Pascal затраты на хранение длины составляют на 3 байта больше.
А на длинных строках операция проверки заранее известной длины занимает меньше времени, чем операция поиска конца строки.
То есть ты считаешь, что перебор строки в поисках концевого нуля - это быстрее?????
Если не память не изменяет такие строки там называются PChar.
Торможение TheBat!, да и другой программы подобной сложности, вызвано вовсе использованием строк того или иного типа. А общей неэффективностью алгоритмов более высокого уровня, построенных поверх строк.
На каком компьютере TheBat! тормозит? На Pentium-I, II, III?
То что тормозят и требуют специального Runtime программы на C# не напрягает?
Я вам сразу сказал - меня не особо интересуют остальные достижения этого человека
Речь-то идёт не только об этих затратах памяти, речь идёт об операциях, которые потом используют этот размер повсеместно по 100500 раз, потому что всё сделано потом с учётом этого размера. Просто прочитать до нуль-символа такую строку нельзя.
И что она даёт, эта ненужная проверка длины, когда не нужна длина?
Я передаю строку в функцию - передаётся адрес начала. Я так могу передавать много раз, при этом передаётся только адрес начала.
А тут как минимум надо передать адрес И ДЛИНУ.
Умножаем на миллиард - получаем общее замедление.
Просто прочитать длину строки (1-2-4 байта)
Просто найти конец строки 0 в строке "hello, world" = прочитать 15 байт, дурачина.
Длина строки (или другим способом определить ее окончание) нужна в подавляющем большинстве случаев:
Вставка в середину (чтобы быть уверенным что не выходишь за пределы строки),
Поиск в строке,
Не надо. В Паскале также передается ТОЛЬКО адрес начала.
Вставка - не такая уж частая операция. Но длину можно узнать ОДИН раз, а потом сто раз использовать, а не хранить её ВСЕГДА рядом, занимая память под это.
Ну, достижение, значит. Это огромный плюс, что он передаёт только адрес (ссылку), а потом 100500 раз читает размер.
2. Если вам нужно ОДИН раз УЗНАТЬ, но чтобы 100 раз ИСПОЛЬЗОВАТЬ, то все равно нужно ХРАНИТЬ то, что вы уже узнали.
2. Программа с строками стиля Паскаль, если ей по алгоритму этого не нужно, может прекрасно также НЕ ЧИТАТЬ уже определенную длину.
То есть нуль-терминированные строки легко передавать, потому что одна строка заканчивается тогда, когда встречается ноль. А ты свои как будешь передавать. Сначала ты будешь должен сообщить, чему равна длина размера, а на той стороне надо будет это помнить.
char
- одна буква в кодировке ASCII занимает один байтw_char
- одна буква в кодировке UTF-16, занимает 2 байта\0
- символ конца строки, используется для того чтобы printf и т.п. функции знали где заканчивается область памяти отведенная под строку.const char *name = "name";
- символ конца строки поставит сам компилятор и длина строки будет не 4 байта, а 5, но при этом strlen должен возвращать длину до \0 т.е. 4 байта, хотя на самом деле хранится 5 байтstd::string
, std::wstring
или Qstring