Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.038 c
14-1104132785
Narik
2004-12-27 10:33
2005.01.16
Разгатка!!! Связь с файлами!!!


1-1103956071
Secam
2004-12-25 09:27
2005.01.16
Индексированный массив ?


14-1104062585
Андрей Червенко
2004-12-26 15:03
2005.01.16
Зацените новую программу Notepad Plus


1-1103284017
kirilllius
2004-12-17 14:46
2005.01.16
Программа для сканирования


1-1104150644
Zhekson
2004-12-27 15:30
2005.01.16
TChart





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский