When can ((Pointer)(P)+1)^ work?

2019-07-13 11:07发布

问题:

I'am working on delphiXE2 and i was working on PInteger. if i did this in my delphi code

var
  P: PInteger;
  testInt: Integer;
  Scores: array[0..4] of Integer=(33,44,56,78,78);
begin
  P := @Scores;
  testInt := (P+1)^;
  WriteLn(testInt);
  ReadLn;
end;

I got this error.

[DCC Error] Project1.dpr(23): E2015 Operator not applicable to this operand type

PS: testInt := (P+1)^; is the 23rd line

However when I try this

var
  PCh: PChar;
  testchar: char;
  str: array[0..4] of char=('a','b','c','d','e');
begin
  PCh := @str;
  testchar := (PCh+1)^;
  WriteLn(testchar);
  ReadLn;
end;

it works well! The console can print 'b'!

I'm not clear about how could this happen and when ((Pointer)(P)+1)^ can work?

回答1:

Pointer arithmetic requires the compiler to know the size of the element that is pointed to. That knowledge is never known for an untyped pointer of type Pointer. So you can never do pointer arithmetic with Pointer.

Delphi has always supported pointer arithmetic for AnsiChar. More recently a compiler directive, POINTERMATH, was added to enable pointer arithmetic on all typed pointers: http://blogs.embarcadero.com/abauer/2008/01/24/38852

Note that the directive enables the additive orithmetic operators and the array indexing operator [].

So, if you enable pointer arithmetic, you can perform arithmetic on all pointers other than untyped pointers. Otherwise it is only supported for pointers to character types or pointers to byte.

With that said, your code would be much cleaner if you wrote P[1] instead. Obviously that would require pointer arithmetic to be enabled.



回答2:

var
  P: PInteger;
  testInt: Integer;
  Scores: array [0..4] of Integer = (33, 44, 56, 78, 78);
begin
  P := @Scores[0];
  testInt := PInteger(UINT(P) + SizeOf(Integer))^;
  WriteLn(testInt);
  ReadLn;
end;

You need to use @Scores[0] to get the first element in array. And to get the next integer in array you need to add SizeOf(Integer) instead of 1 .



回答3:

((Pointer)(P)+1)^ can work if you use P[1] instead.

You can rewrite your code

var
  P: PIntegerList;
  testInt: Integer;
  Scores: array[0..4] of Integer=(33,44,56,78,78);
begin
  P := @Scores;
  testInt := P^[1];
  WriteLn(testInt);
  ReadLn;
end;

You don't need pointer arythmetic here (let compiler do his job for you).