Текущий архив: 2009.12.13;
Скачать: CL | DM;
Внизxor первым 4 байтам string одной строкой Найти похожие ветки
← →
Nucer (2009-10-23 19:41) [0]Можно ли исправить? Или сделать 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;
← →
palva © (2009-10-23 19:53) [1]А посмотрите адрес, по которому происходит access violation
Если он нечетный, то это из-за выравнивания.
А IntToHex, наверно, обрабатывает число побайтно, поэтому ошибок не происходит.
← →
palva © (2009-10-23 19:57) [2]Как бы то ни было, так делать нельзя. 4 последовательных байта не всегда могут рассматриваться как целое число. Адрес первого байта должен делиться на 2 (может быть, даже на 4, поправьте, если ошибаюсь).
← →
sniknik © (2009-10-23 20:21) [3]
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;
← →
begin...end © (2009-10-24 10:54) [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])^ := ...
автоматически создаётся копия строки.
← →
Nucer (2009-10-24 12:19) [5]Большое спасибо за подробные ответы.
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).
← →
sniknik © (2009-10-24 12:39) [6]> 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;
← →
sniknik © (2009-10-24 12:40) [7]а, ну да
> // access violation
здесь лишнее (издержки копи пасте)
Страницы: 1 вся ветка
Текущий архив: 2009.12.13;
Скачать: CL | DM;
Память: 0.46 MB
Время: 0.007 c