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!
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;