Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Как работать с указателями?


Автор: RideX 24.4.2006, 15:40
Здравствуйте! Подскажите пожалуйста, как работать с указателями, не знаю как это сделать без асма? :-/ Вот пример:
Код

// Some code...
 pMemory := MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
 MainStruct := pMemory;
 asm
  mov eax, dword ptr[MainStruct]
  add eax,14 // SizeOf(MainStruct)
  mov dword ptr[SubStruct],eax
 end;
 
// Some code...

 asm
  mov eax, dword ptr[SubStruct]
  add eax,4
  mov ecx,i // i = SubStruct.Length;
  mov dx,wSign
  @loop:
    add eax,1
    cmp word ptr[eax],dx
    je @found

    dec ecx
    test ecx,ecx
    jnz @loop
    xor eax,eax
    mov dword ptr[pPos],eax
    jmp @end

  @found:
    and eax,0000FFFFh
    mov dword ptr[pPos],eax

  @end:
 end;

// Some code...
 

Автор: Albinos_x 24.4.2006, 16:33
DRKB (Delphi Russian Knowledge Base)

Цитата

 var  
  p1 : ^String;  
 s1 : String;  
  begin  
  s1 := 'NotTest';  
 new (p1);  
 p1 := @s1;  
 p1^ := 'Test';  
 Label1.Caption := s1  

Цитата

Арифметика указателей 
 
Сначала короткое объяснение арифметике указателя. Когда вы имеете дело с динамическими страницами памяти, то все, что вы имеете - это указатели на начала блоков памяти. Вы хотите просмотреть всю строку памяти, чтобы понять какие функции необходимы для работы с данными, хранящимися в памяти? Это возможно путем изменения места в памяти, на которое указывает указатель. Это называется арифметикой указателя. 
Основополагающая идея при занятиях арифметикой с указателем - указатель должен быть увеличен на значение корректного приращения. (Корректное приращение определяется размером объекта, на который показывает указатель. Например, char = 1 байт; integer = 2 байта; double = 8 байт и т.д.) Функции Inc() и Dec() изменяют значение корректного приращения. (Компилятор знает правильный размер объекта.) 
Если вы осуществляете динамическое распределение памяти, то делать это можно примерно так: 

uses WinCRT; 
procedure TForm1.Button1Click(Sender: TObject); 
var 
  MyArray: array[0..30] of char; 
  b: ^char; 
  i: integer; 
begin 
  StrCopy(MyArray, 'Дельфи - рулез фарева!'); 
    {помещаем что-то в память для организации указателя} 
  b := @MyArray; { назначаем указатель на текущую позицию памяти } 
  for i := StrLen(MyArray) downto 0 do 
  begin 
    write(b^); { пишем символ в текущую позицию указателя. } 
    inc(b); { перемещаем указатель на следующий байт памяти } 
  end; 
end; 

Нижеследующий код демонстрирует работу функций Inc() и Dec(), увеличивающих или уменьшающих указатель на размер соответствующего типа: 

var 
  P1, P2: ^LongInt; 
  L: LongInt; 
begin 
  P1 := @L; { назначаем оба указателя на одно и то же место } 
  P2 := @L; 
  Inc(P2); { Увеличиваем один } 
  { Здесь мы получаем разницу между смещениями двух 
  указателей. Поскольку первоначально они указывали на одно 
  и то же место памяти, то результатом данного вызова 
  будет разница между двумя указателями после вызова Inc(). } 
  L := Ofs(P2^) - Ofs(P1^); { L = 4; т.е. sizeof(longInt) } 
end; 

Вы можете изменить тип объекта, на который указывает P1 и P2, на какой-то другой и убедиться, что (SizeOf(P1^)) всегда возвращает величину корректного приращения (проще сказать, что это размер объекта - В.О.). 
 

Автор: RideX 24.4.2006, 20:12
Цитата(Albinos_x @  24.4.2006,  19:33 Найти цитируемый пост)
Функции Inc() и Dec() изменяют значение корректного приращения.

Ага, вот в чём фишка! Ну теперь всё понятно, сорри за ламеризм %) Вот решение по навигации в памяти на примере элементарного поиска сигнатуры в файле.

Код

procedure TForm1.Button1Click(Sender: TObject);
const
  wSign: WORD = $3231;
var
  hFile: THandle;
  szFileName: PChar;
  fSize, i, n: DWORD;

  hFileMap: THandle;
  pMemory : Pointer;
  pPos    : Pointer;
begin
 if not OpenDialog1.Execute then
  Exit;

 Memo1.Clear;
 szFileName := PChar(OpenDialog1.FileName);
 Edit1.Text := szFileName;

 hFile := CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, nil,
                                           OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
 fSize := GetFileSize(hFile, nil);
 hFileMap := CreateFileMapping(hFile, nil, PAGE_READONLY, 0, 0, nil);
 pMemory := MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);

 n := 0;
 pPos := pMemory;
 for i := 0 to fSize - 1 do begin
  if WORD(pPos^) = wSign then begin
    n := i;
    Break;
  end;
  Inc(DWORD(pPos));
 end;

 UnmapViewOfFile(pMemory);
 CloseHandle(hFileMap);
 CloseHandle(hFile);

 Memo1.Lines.Add('Filesize: ' + IntToStr(fSize));
 Memo1.Lines.Add('Founded in: ' + IntToHex(n, 8));
end;
  

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)