Search code examples
delphipascal

How do you access different data types using Pascal pointers?


In general I have a problem figuring out how to handle pointer conversions in pascal. If I wanted a word from my byte pointer wouldn't I do something like:

type WordPtr = ^Word;
var P1, P2 : ^Byte; w, byteoffset : word; 
begin 
  P1:=SomeGetMemVar;  byteoffset:=8;
  w:=WordPtr(@P1^[byteoffset])^; { invalid qualifiers at the [ }
  w:=WordPtr(P1[byteoffset])^; { invalid qualifiers at the [ }
  w:=WordPtr(P1+byteoffset)^; { type mismatch }
end;

Apparently not, because it doesn't work as shown in the comments.

How do I get this to work in Pascal? C would be:

uint16_t byteoffset=8;
uint8_t* P1=(uint8_t*) malloc(1000);
uint16_t w;
w=*((uint16_t*) (P1+byteoffset));   // method 1
w=*((uint16_t*) (&P1[byteoffset])); // method 2

Thanks!


Solution

  • In order to treat pointers as arrays, make sure that {$POINTERMATH ON} is enabled. It already is for PByte (don't use ^Byte directly), but not for most pointer types by default.

    Try something more like this:

    {$POINTERMATH ON}
    var
      P1 : PByte;
      w, byteoffset : Word;
    begin 
      P1 := SomeGetMemVar;
      byteoffset := 8;
      w := PWord(@P1[byteoffset])^;
      //or:
      w := PWord(P1+byteoffset)^;
    end;
    

    Alternatively, use Move() instead of casting pointers:

    var
      P1 : PByte;
      w, byteoffset : Word;
    begin 
      P1 := SomeGetMemVar;
      byteoffset := 8;
      Move(P1[byteoffset], w, SizeOf(w));
      //or:
      Move((P1+byteoffset)^, w, SizeOf(w));
    end;
    

    For older compilers that don't support {$POINTERMATH}, you can type-cast to PAnsiChar (which always supported pointer math by default):

    var
      P1 : PByte;
      P2: PAnsiChar;
      w, byteoffset : Word;
    begin 
      P1 := SomeGetMemVar;
      P2 := PAnsiChar(P1);
      byteoffset := 8;
      w := PWord(@P2[byteoffset])^;
      //or:
      w := PWord(P2+byteoffset)^;
    end;
    

    Or, just increment the PByte pointer manually:

    var
      P1, P2 : PByte;
      w, byteoffset : Word;
    begin 
      P1 := SomeGetMemVar;
      byteoffset := 8;
      P2 := P1;
      Inc(P2, byteoffset);
      w := PWord(P2)^;
    end;