Форум: "Основная";
Текущий архив: 2005.01.16;
Скачать: [xml.tar.bz2];
ВнизКак изменть значение указателя? Найти похожие ветки
← →
Дурдом (2005-01-03 02:40) [0]Доброй ночи!
Можно ли средствами Делфи не прибегая к инлайн-ассемблеру сделать следующее:
var
A1:array[0..$FF] of byte;
FileMapped:pointer; //указатель на кусок памяти
n:integer;
---
begin
for i:=0 to $FF do
A1[i]:=значение байта (по адресу (указателя на кусок памяти+i))
Это означает, что FileMapped указывает на некий массив байт, и надо заполнить массив A1 байтами, на которые указывает FileMapped (пододвигая значение указателя на 1 в право, но если можно по-другому - я не против).
← →
GuAV © (2005-01-03 02:57) [1]Для арифметических операций с указателями их можно приводить к целочисленному 32 разрядному типу.
A1[i]:=PByte(Integer(FileMapped)+i)^
можно привести указатель к указателю на массив байтов.
A1[i]:=PByteArray(FileMapped)[i]
А ещё можно (я бы сделал имеено так) - воспользоваться Move
Move(FileMapped^, A1[Low(A1)], SizeOf(A1));
← →
programania © (2005-01-03 02:58) [2]move(ptr(integer(FileMapped)+i)^,A1[i],1);
а короче
move(FileMapped^,A1,sizeOf(A1));
← →
begin...end © (2005-01-03 09:58) [3]> Дурдом (03.01.05 02:40)
Приведу ещё один вариант, хотя я бы тоже воспользовался Move или CopyMemory.var
A1: array [0..$FF] of Byte;
FileMapped: Pointer;
I: Integer;
begin
for I := 0 to $FF do
A1[I] := PByteArray(FileMapped)[I]
end.
← →
begin...end © (2005-01-03 10:08) [4]Извиняюсь, просмотрел - это уже предложили в [1].
← →
TUser © (2005-01-03 12:45) [5]А за что всем так нравится Move для этой задачи?
← →
begin...end © (2005-01-03 12:47) [6]> [5] TUser © (03.01.05 12:45)
А за что оно тебе так не нравится?
← →
TUser © (2005-01-03 13:32) [7]Просто непонятно - зачем сначала копировать/перемещать кусок памяти, а потом читать, если можно сразу прочитать через приведение к массиву или с индексной арифметикой ...
← →
begin...end © (2005-01-03 13:36) [8]> [7] TUser © (03.01.05 13:32)
> зачем сначала копировать/перемещать кусок памяти, а потом
> читать
См. [0]:
> FileMapped указывает на некий массив байт, и надо заполнить
> массив A1 байтами, на которые указывает FileMapped
← →
Дурдом (2005-01-03 13:57) [9]Ух! круто! Оба способа подошли: и move, и PByteArray. В случае с PByteArray всё стало происходить так, как я и задумывал(циклом), а в случае с move, всё сошлось на долгой процедуре со строковыми командами "repCC movsX" - но так я уже сам сделал на Асме. С циклом поэксперементировать интересно (вдруг быстрее будет :).
---
Шпасибо =)
← →
Fay © (2005-01-03 17:53) [10]2 TUser © (03.01.05 13:32) [7]
Move побыстрее будет.
← →
GuAV © (2005-01-03 18:04) [11]Самым быстрым же однако в общем случае будет присвоение массива целиком.
type
TA1 = array [0..$FF] of Byte;
var
A1: TA1;
FileMapped: Pointer;
I: Integer;
begin
A1 := TA1(FileMapped^);
end;
← →
имя (2005-01-03 18:22) [12]Удалено модератором
← →
GuAV © (2005-01-03 18:33) [13]Автор (03.01.05 18:22) [12]
А move будет быстрее при больших массивах.
Не-а.
← →
Fay © (2005-01-03 18:56) [14]2 GuAV © (03.01.05 18:33) [13]
В данном случае ([0..$FF]
) Move медленнее. Но сравните при[0..320]
, к примеру.
← →
GuAV © (2005-01-03 19:11) [15]Fay © (03.01.05 18:56) [14]
Всё равно присвоение немного быстрее.
хинт:
type
TA1 = array [0..320] of Byte;
var
A1: TA1;
FileMapped: Pointer;
begin
A1 := TA1(FileMapped^); // поставьте тут BreakPoint и посмотрите на CPU. А потом посмотрите на Move.
end;
← →
Fay © (2005-01-03 19:26) [16]2 GuAV © (03.01.05 19:11) [15]
Я это уже сделал. На миллионе итераций, чтобы было видно разницу тупо по времени. Move быстрее, при 999 (взял с потолка) ещё заметнее.
← →
имя (2005-01-03 19:46) [17]Удалено модератором
← →
имя (2005-01-03 19:52) [18]Удалено модератором
← →
Fay © (2005-01-03 20:03) [19]2 АвторДурдом (03.01.05 19:46) [17]
А мне пофинг - я время считал.
← →
Дурдом (2005-01-03 20:19) [20]Дык об одном и том-же говорим ;) move() буит рулить при крупненьких массивах.
---
А такой вариант как сделать(компилер материт):
type
AT: array[0..$0F] of byte;
var
FileMapped:pointer;
A1: AT;
i:integer;
begin
for i:=0 to $0F do
A1:=AT((FileMapped+i)^);
????
← →
begin...end © (2005-01-03 20:28) [21]> [20] Дурдом (03.01.05 20:19)
О боже, а что Вы хотели сделать-то?
← →
Fay © (2005-01-03 20:29) [22]Pointer(DWORD(FileMapped)+i) ?
← →
begin...end © (2005-01-03 20:39) [23]А-а, это... Ну тогда вот так ещё можно:
type
AT = array [0..$0F] of Byte;
var
FileMapped: Pointer;
A1: AT;
I: Integer;
begin
for I := 0 to $0F do
A1[I] := PByte(PChar(FileMapped) + I)^
end.
← →
GuAV © (2005-01-03 20:56) [24]var
M: array[0..1000] of integer;
FileMapped: Pointer = @M;
procedure P1;
type
TA1 = array [0..999] of Byte;
var
A1: TA1;
begin
A1 := TA1(FileMapped^);
end;
procedure P2;
type
TA1 = array [0..999] of Byte;
var
A1: TA1;
begin
Move(FileMapped^, A1 , SizeOF(A1));
end;
procedure TForm1.Button1Click(Sender: TObject);
const
TestCount = 1000000;
var
A, B: Cardinal; i: integer;
begin
A := GetTickCount;
for i := 0 to TestCount do P1;
A := GetTickCount - A;
B := GetTickCount;
for i := 0 to TestCount do P2;
B := GetTickCount - B;
Caption := Format("P1 = %d, P2 = %d", [A, B]);
// P1 = 283, P2 = 350
// win98, D7, {$O+}
// для 320 разрыв ещё существеннее
end;
← →
GuAV © (2005-01-03 21:34) [25]begin...end © (03.01.05 20:39) [23]
к PChar приводить не хорошо. символ это не обязательно байт.
← →
Дурдом (2005-01-03 21:48) [26]УРА!!! Как раз почти как я хотел!
type
TA = array [0..$0F] of Byte;
var
hFile1Map:pointer;
i:integer;
begin
Sign1:=TA(pointer(dword(hFile1Map)+i)^);
end;
[IMHO]
Благо, это не С++ - там вообще в типах чёрт голову сломит, и компилер там вредный. Мдя, программер из меня...
[/IMHO]
← →
begin...end © (2005-01-03 21:49) [27]> [25] GuAV © (03.01.05 21:34)
The generic PChar represents a pointer to a Char (that is, in its current implementation, to an AnsiChar). А AnsiChar - это 1 байт, в отличие от WideChar. Разве нет?
← →
GuAV © (2005-01-03 21:56) [28]begin...end © (03.01.05 21:49) [27]
The generic PChar represents a pointer to a Char (that is, in its current implementation, to an AnsiChar).
What happened to your code when the implementation will have changed ?
← →
begin...end © (2005-01-03 21:59) [29]> [28] GuAV © (03.01.05 21:56)
[25]: символ это не обязательно байт.
Вопрос: в каком случае СЕЙЧАС Char - это не байт?
> What happened to your code when the implementation will
> have changed ?
Я не доживу, мне кажется.
← →
GuAV © (2005-01-03 22:03) [30]begin...end © (03.01.05 21:59) [29]
Сейчас - в случае другого pascal-совместимого транслятора. А в будущем - возможно очень скоро.
> What happened to your code when the implementation
> will have changed ?
кстати, правильно совсем наоборот :-)
← →
begin...end © (2005-01-03 22:08) [31]> [30] GuAV © (03.01.05 22:03)
Тем не менее, Borland, например, в модуле StrUtils спокойно пишет Inc(P), где P: PChar.
В будущем может случиться что угодно. Например, что мешает увеличиться или уменьшиться DWORD"у?
← →
GuAV © (2005-01-03 22:13) [32]begin...end © (03.01.05 22:08) [31]
StrUtils для работы со строками. там Inc(P) заставит P указывать на следующий символ, не важно занимает ли он 1 или 2 байта в текущей реализации.
Кроме того наличие у Borland implementation-specific кода я считаю нормальным, т.к. они отвечают за этот самый implementation, а в своём коде я бы избежал таких конструкций.
← →
GuAV © (2005-01-03 22:15) [33]begin...end © (03.01.05 22:08) [31]
Например, что мешает увеличиться или уменьшиться DWORD"у?
DWORD aka LongWord по определению 32 байта. а вот Cardinalу действительно никто не запрещает изменить размер, и возможно он изменится когда-нибудь.
← →
begin...end © (2005-01-03 22:20) [34]> [32] GuAV © (03.01.05 22:13)
> там Inc(P) заставит P указывать на следующий символ, не
> важно занимает ли он 1 или 2 байта в текущей реализации.
Почему? По-моему, указатель просто будет указывать на следующий байт, а не перескакивать, например, на 2 байта.
← →
begin...end © (2005-01-03 22:23) [35]> [33] GuAV © (03.01.05 22:15)
> DWORD aka LongWord по определению 32 байта.
Что-то многовато :-)
Нельзя исключать, что через 100 лет словом будет называться 4 байта, например.
← →
GuAV © (2005-01-03 22:27) [36]program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
P1: PAnsiChar;
P2: PWideChar;
P3: PLongWord;
begin
P1 := "Hello";
P2 := "world";
P3 := @HInstance;
WriteLn(IntToHex(Integer(P1),8));
WriteLn(IntToHex(Integer(P2),8));
WriteLn(IntToHex(Integer(P3),8));
Inc(P1);
Inc(P2);
Inc(P3);
WriteLn(IntToHex(Integer(P1),8));
WriteLn(IntToHex(Integer(P2),8));
WriteLn(IntToHex(Integer(P3),8));
ReadLn;
end.
← →
begin...end © (2005-01-03 22:32) [37]> [36] GuAV © (03.01.05 22:27)
Да, я уже в CPU посмотрел, в случае Inc(PWideChar) прибавляется смещение 2.
Но всё же я считаю, что эти предосторожности лишние. Ты меня не переубедишь :-)
P.S. Пойду спать.
← →
GuAV © (2005-01-03 22:34) [38]begin...end © (03.01.05 22:23) [35]
rtfm: fundamental and generic types
type->F1->declaring types->see also->about types
← →
GuAV © (2005-01-03 22:36) [39]DWORD - fundamental, а PChar - generic.
← →
Fay © (2005-01-04 00:16) [40]2 GuAV © (03.01.05 20:56) [24]
Мне седня удалось получить результаты и в пользу Move, и "не в пользу". Причём с одними и теми же условиями - просто в разное время 8)
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2005.01.16;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.039 c