- - * - WhiteUnicorn - * - -




* #WhiteUnicorn/ StartPage/ Documentation/DelphiFAQ >


3210:A better way to do pointer arithmetic

KEYWORDS: pointer arithmetic, pointers, conversion, migration, dereference ARE

(*

This document demonstrates a technique for incrementing pointers under
Borland Pascal 7.0, Turbo Pascal for Windows, and Delphi.

Send it any pointer, and an offset of the pointer you really
want (yes, huge pointers > 64 are supported) and it will return
a pointer to that location. Unlike most other huge pointer code,
this snippet will take into account the fact that you may be
sending a pointer that does not have a zero based offset.

Be aware that you cannot access memory that crosses a 64k
boundary in Win16. If you need to access a record that
spans a 64K boundary, you must first grab the portion of the
record that exists before the boundary, then grab the second
portion that exists above the boundary, and piece them together.

Note the function is designed to be upwardly portable to
Win32 where there is no need to do pointer manipulation
since Win32 uses a flat (non-segmented) memory model where
there are no 64k boundaries. While using the function call
to get a pointer under Win32 is not exactly efficient, it
will make porting legacy 16 bit code to Win32 a breeze!

*)

type
  PtrRec = record
    Lo : Word;
    Hi : Word;
  end;
  PHugeByteArray = ^THugeByteArray;
  THugeByteArray = array[0..0] of Byte;

function GetBigPointer(lp : pointer;
                       Offset : LongInt) : Pointer;

begin
 {$IFDEF WIN32}
  GetBigPointer := @PHugeByteArray(lp)^[Offset];
 {$ELSE}
  Offset := Offset + PTRREC(lp).Lo;
  GetBigPointer := Ptr(PtrRec(lp).Hi + PtrRec(Offset).Hi * SelectorInc,
                       PtrRec(Offset).Lo);
 {$ENDIF}
end;


{Lets test it!}

procedure TForm1.Button1Click(Sender: TObject);
var
  h  : THandle; {handle to the memory block}
  p  : pointer; {pointer to the memory block}
  p2 : pointer; {pointer for testing}
  p3 : pointer; {pointer for testing}
begin
 {allocate two hundred thousand bytes of memory and zero out}
  h := GlobalAlloc(GHND, 200000);

 {get a pointer to the allocated memory}
  p := GlobalLock(h);

 {get a pointer to the byte at index 75000}
  p2 := GetBigPointer(p, 75000);

 {get a pointer to the byte 80000 bytes from p2}
  p3 := GetBigPointer(p2, 80000);

 {verify the byte p3 points to is zero}
  Memo1.Lines.Add(IntToStr(pByte(p3)^));

 {change the value of the byte p3 points to}
  pByte(p3)^ := 10;

 {verify the change}
  Memo1.Lines.Add(IntToStr(pByte(p3)^));

 {free the memory}
  GlobalUnlock(h);
  GlobalFree(h);
end;

end.

<end of ti>

        TI



* #WhiteUnicorn/ StartPage/ Documentation/DelphiFAQ >



- - * - Anastasija aka WhiteUnicorn - * - - LJLiveJournal
PFPhotoFile