Двоичное представление строки
Модератор: Модераторы
Двоичное представление строки
Не подскажите, как узнать двоичное представление строки? Вид в котором она содержится в памяти.
Нет, я имел в виду как практически.
Например строка 'World'. Как узнать ее двоичное представление? Есть функция по преобразованию?
Например строка 'World'. Как узнать ее двоичное представление? Есть функция по преобразованию?
Просто приведи строку к указателю, по нему содержимое и лежит, читай-извлекай чем хочешь. К типизированному, возможно, придётся двумя кастами: PByte(pointer(s)). Для shortstring — pointer(PChar(@s) + 1) вместо pointer(s), можно, конечно, просто @s[1], но с включенной range checking это упадёт на пустой строке.
Последний раз редактировалось runewalsh 07.09.2015 17:51:27, всего редактировалось 1 раз.
Извиняюсь, нужно именно shortstring. Как-то можно посмотреть область памяти, где она лежит?
Отредактировал сообщение. А вообще shortstring не нужна. Никогда. ;)
1)
shortstring нужна всегда, с ней проще, и она быстрее работает.
2)
— Can't read or write variables of this type
shortstring нужна всегда, с ней проще, и она быстрее работает.
2)
Код: Выделить всё
writeln('Str - ', pointer(PChar(@Str) + 1));shortstring нужна всегда, с ней проще, и она быстрее работает.
Нет. Во-первых, никогда нет. Во-вторых, пример: по умолчанию константы типа shortstring независимо от реальной длины строк с радостью занимают в исполняемом файле все 256 байт, а константы ansistring — нет. В-третьих, счастливо обрубать строки на 255 символах. В-четвёртых, shortstring при присваивании всегда копируются, а у ansistring есть счётчик ссылок.
Can't read or write variables of this type
Я сказал, как получить указатель на данные строки в памяти. Что с ними делать дальше — твоё дело. Должно быть более-менее очевидно, что writeln указателя — странная операция, нэ? Если хочешь вывести шестнадцатеричный дамп, то:
Код: Выделить всё
{$coperators+} // +=
{$modeswitch result+} // result в функциях
{$h+} // string = ansistring
function HexDump(const s: string): string;
var
bytes: PByte;
i: integer;
begin
result := '';
bytes := pointer(s);
for i := 0 to length(s) * sizeof(s[1]) - 1 do
result += HexStr(bytes[i], 2) + ' ';
end;
writeln(HexDump('hello')); // => 68 65 6C 6C 6F
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
Pasha-V писал(а):Извиняюсь, нужно именно shortstring. Как-то можно посмотреть область памяти, где она лежит?
оператором взятия адреса -- @
1) Нет, ansistring не подходит.
Простой пример — сортировка динамического и статического массивов. Динамический медленнее на 40%.
2) Если использовать указатель, то нужно так?
А дальше?
Главное преимущество строк типа AnsiString по сравнению с короткими строками — отсутствие каких-либо ограничений на длину обрабатываемых данных. Но это преимущество имеет и обратную сторону медали — работа с динамически выделяемой памятью сопряжена со значительными накладными расходами. Как только переменной такого типа присваивается очередное значение, имеющее длину, отличную от длины предыдущего значения, приходится возвращать ранее занимаемый ресурс и выделять место под новое значение переменной. Это неизбежно приводит к появлению разрозненных освобожденных участков памяти, выполнению дополнительных работ по "уборке мусора" и, как следствие, к замедлению работы программы.
Простой пример — сортировка динамического и статического массивов. Динамический медленнее на 40%.
2) Если использовать указатель, то нужно так?
Код: Выделить всё
var
P: ^string;
S: string;
begin
S := 'World';
А дальше?
zub писал(а):сегодня он +1, завтра -1, а в четверг +8
Имхо, для «коротких» строк предположение о длине в нулевом символе вполне безопасно.
zub писал(а):@Str[1]
Будет «ложное срабатывание» рейнджчека на пустой строке, говорю же. Ещё один довод против shortstring, «длинные» к указателям приводятся без проблем!
Pasha-V писал(а):Простой пример — сортировка динамического и статического массивов. Динамический медленнее на 40%.
Уж не знаю, как ты получил этот результат, но это неправда, потому что сортировка обоих массивов тривиально сводится к Sort(data: PType; count: integer).
Pasha-V писал(а):работа с динамически выделяемой памятью сопряжена со значительными накладными расходами
Больше слушай, да. Присваивание уже существующей строки не выделяет память, бтв. Единственный сценарий, в котором «длинные строки» работают медленнее, чем могли бы — это когда к длинной по одной присоединяются 9000 коротких. Для таких сценариев, которые для тебя вроде как не актуальны и не собираются быть актуальными, существует паттерн или готовый класс String Builder.
Уж не знаю, как ты получил этот результат
Вообще, это известный факт — динамика медленнее. Можешь сам проверить. Моя программка:
Код: Выделить всё
uses
sysutils, dateutils;
const
Len = 16000000; // длина массива случайных чисел
Ran = 16000000; // диапазон случайных чисел
type
TStat = array[1..Len] of longword;
TDyn = array of longword;
PStat = ^TStat;
procedure JotMess;
var
w: longword;
begin
assign(stdout, 'C:\Mess.txt');
rewrite(stdout);
randomize;
for w := 1 to Len do
write(stdout, random(Ran) + 1, ' ');
close(stdout);
end;
procedure Make(stat: PStat; dyn: TDyn; s: char);
var
w: longword;
begin
assign(input, 'C:\Mess.txt');
reset(input);
if s = 'S' then
for w := 1 to Len do
read(stat^[w], s)
else
for w := 0 to Len - 1 do
read(dyn[w], s);
end;
procedure CSort(arr: PStat);
var
b: array[1..Ran + 1] of byte;
i, j, k: longword;
begin
fillbyte(b, Ran + 1, 0);
for i := 1 to Len do
inc(b[arr^[i]]);
k := 1;
for j := 1 to Ran + 1 do
for i := 1 to b[j] do
begin
arr^[k] := j;
inc(k);
end;
end;
procedure CSort(arr: TDyn);
var
b: array of byte;
i, j, k: longint;
begin
setlength(b, Ran + 1);
for i := 0 to Len - 1 do
inc(b[arr[i]]);
k := 0;
for j := 0 to Ran do
for i := 0 to b[j] - 1 do
begin
arr[k] := j;
inc(k);
end;
end;
procedure Jot(stat: PStat; dyn: TDyn; a: char);
var
w: longword;
begin
assign(stdout, 'C:\' + a + '.txt');
rewrite(stdout);
if a = 'S' then
for w := 1 to Len do
write(stdout, stat^[w], ' ')
else
for w := 0 to Len - 1 do
write(stdout, dyn[w], ' ');
close(stdout);
end;
var
Stat: PStat;
Dyn: TDyn;
First: tdatetime;
begin
JotMess;
new(Stat);
Make(Stat, Dyn, 'S');
First := now;
CSort(Stat);
writeln('Stat: ', millisecondsbetween(First, now));
Jot(Stat, Dyn, 'S');
dispose(Stat);
setlength(Dyn, Len);
Make(Stat, Dyn, 'D');
First := now;
CSort(Dyn);
writeln('Dyn: ', millisecondsbetween(First, now));
Jot(Stat, Dyn, 'D');
finalize(Dyn);
end.
Pasha-V писал(а):Можешь сам проверить.
Проверил. В Debug действительно быстрее (800 vs 1250). Но цифры Debug не имеют значения. В Release поровну (540 vs 550 лол). И те 10 мс разницы — SetLength временного массива, в реальности же сортировки производятся не подсчётом и память не распределяют вообще и что статический, что динамический будут одинаковы с точностью до такта.
runewalsh
>>Имхо, для «коротких» строк предположение о длине в нулевом символе вполне безопасно.
>>Будет «ложное срабатывание» рейнджчека на пустой строке, говорю же. Ещё один довод против shortstring, «длинные» к указателям приводятся без проблем!
Проверку на нулевую длину никто не отменял. Зато эта адресация монопесуальна к тупу строки - синтаксически одинакова что для "длинных", что для "коротких", пусть о внутреннем устройстве строки заботится компилятор, это его работа
>>Имхо, для «коротких» строк предположение о длине в нулевом символе вполне безопасно.
>>Будет «ложное срабатывание» рейнджчека на пустой строке, говорю же. Ещё один довод против shortstring, «длинные» к указателям приводятся без проблем!
Проверку на нулевую длину никто не отменял. Зато эта адресация монопесуальна к тупу строки - синтаксически одинакова что для "длинных", что для "коротких", пусть о внутреннем устройстве строки заботится компилятор, это его работа
