![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
xor первым 4 байтам string одной строкой
Nucer © (2009-10-23 19:41:00)Можно ли исправить? Или сделать xor одной строкой в любом случае не получится?
var
s: string;
begin
s := #1#2#3#4;
ShowMessage(IntToHex(PInteger(s)^, 8)); // работает (04030201)
PInteger(s)^ := PInteger(s)^ xor $FFFFFFFF; // access violation
end;
sniknik (2009-10-24 12:40:00) [1]а, ну да
> // access violation
здесь лишнее (издержки копи пасте)
sniknik (2009-10-24 12:39:00) [2]> PInteger(@sd[1]) равнозначно PInteger(sd).
э не, просто преобразование адреса к нужному типу, и взятие элемента из этого адреса и получение его адреса, разные вещи. код генерится разный.
вот результат (получаемый адрес) в данном случае одинаковый.
есть еще вариант. (сразу не смог вспомнить функцию, потом вспомнил как можно посмотреть :о))
var
s: string;
begin
s := #1#2#3#4;
UniqueString(s);
ShowMessage(IntToHex(PInteger(s)^, 8)); // работает (04030201)
PInteger(s)^ := PInteger(s)^ xor $FFFFFFFF; // access violation
end;
Nucer (2009-10-24 12:19:00) [3]Большое спасибо за подробные ответы.
var
sc, sd: string;
t: string;
begin
sc := #1#2#3#4;
SetLength(sd, 4);
sd[1] := #1;
sd[2] := #2;
sd[3] := #3;
sd[4] := #4;
t := t + Format('%x: %x', [Integer(sc), PInteger(sc)^]) + #13#10;
PInteger(@sc[1])^:= PInteger(@sc[1])^ xor $FFFFFFFF;
t := t + Format('%x: %x', [Integer(sc), PInteger(sc)^]) + #13#10;
t := t + Format('%x: %x', [Integer(sd), PInteger(sd)^]) + #13#10;
PInteger(@sd[1])^:= PInteger(@sd[1])^ xor $FFFFFFFF;
t := t + Format('%x: %x', [Integer(sd), PInteger(sd)^]) + #13#10;
ShowMessage(t);
end;
В результате выводится сообщение:
45228C: 4030201
95359C: FBFCFDFE
95354C: 4030201
95354C: FBFCFDFE
В случае с sd, как оказалось, PInteger(@sd[1]) равнозначно PInteger(sd).
begin...end (2009-10-24 10:54:00) [4]> Nucer (23.10.09 19:41)
Не уверен (сейчас Delphi под рукой нет), но думаю, что Ваш пример не работает потому, что тело строки в данном случае является константой , и присвоениеs := #1#2#3#4сводится к записи в переменнуюsадреса этого тела. Тело такой строки-константы (сформированное, конечно, ещё на этапе компиляции) во время работы программы находится в области памяти с правами только на чтение , поэтому у Вас и не получается внести туда изменения. Дело изменится, если строка не будет константой (вероятно, в Вашей реальной программе она таковой и не является, иначе "отxorенную" строку Вы бы тоже задали как константу):
begin
SetLength(s, 4);
s[1] := #1;
s[2] := #2;
s[3] := #3;
s[4] := #4;
ShowMessageFmt('%x', [PInteger(s)^]);
PInteger(s)^ := PInteger(s)^ xor $FFFFFFFF; // должно работать
ShowMessageFmt('%x', [PInteger(s)^])
end.
Код из [3] работает, вероятно, потому, что в ходе присвоенияPInteger(@s[1])^ := ...автоматически создаётся копия строки.
sniknik (2009-10-23 20:21:00) [5]
var
s: string;
begin
s:= #1#2#3#4;
ShowMessage(IntToHex(PInteger(@s[1])^, 8)); // работает (04030201)
PInteger(@s[1])^:= PInteger(@s[1])^ xor $FFFFFFFF;
end;
palva (2009-10-23 19:57:00) [6]Как бы то ни было, так делать нельзя. 4 последовательных байта не всегда могут рассматриваться как целое число. Адрес первого байта должен делиться на 2 (может быть, даже на 4, поправьте, если ошибаюсь).
palva (2009-10-23 19:53:00) [7]А посмотрите адрес, по которому происходит access violation
Если он нечетный, то это из-за выравнивания.
А IntToHex, наверно, обрабатывает число побайтно, поэтому ошибок не происходит.