Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.01.16;
Скачать: CL | DM;

Вниз

Как изменть значение указателя?   Найти похожие ветки 

 
Дурдом   (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;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.05 c
8-1097251674
Delphi5.01
2004-10-08 20:07
2005.01.16
Resample Image: Bicubic, Bicubic Smoother, Bicubic Sharper, ...


1-1103893292
Боян Георгиев
2004-12-24 16:01
2005.01.16
Как запишить .ехе файл в програме?


3-1102850754
syte_ser78
2004-12-12 14:25
2005.01.16
кодировка в paradox 7


1-1103972269
Volfram
2004-12-25 13:57
2005.01.16
TImageList : пара ламерских вопросов.


11-1085755191
Grey
2004-05-28 18:39
2005.01.16
AutoSize...