【问题标题】:When can ((Pointer)(P)+1)^ work?((Pointer)(P)+1)^ 什么时候可以工作?
【发布时间】:2013-10-22 06:13:47
【问题描述】:

我正在研究 delphiXE2,我正在研究 PInteger。 如果我在我的 delphi 代码中这样做

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;

我收到了这个错误。

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

PS:testInt := (P+1)^;是第23行

但是当我尝试这个时

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;

效果很好! 控制台可以打印'b'!

我不清楚这是怎么发生的,什么时候 ((Pointer)(P)+1)^ 可以工作?

【问题讨论】:

  • Delphi pointer arithmetic。只需添加指针算术编译器指令(适用于 D2009+)。
  • 我看不出有任何理由在 Delphi 中使用这种糟糕的语法。请改用“p: PIntegerList”和标准语法“p[i]”来访问项目。

标签: delphi pointers delphi-xe2 pchar


【解决方案1】:

指针算法要求编译器知道所指向元素的大小。对于 Pointer 类型的无类型指针,永远不会知道该知识。所以你永远不能用 Pointer 做指针运算。

Delphi 一直支持 AnsiChar 的指针运算。最近添加了一个编译器指令POINTERMATH,以启用对所有类型指针的指针运算:http://blogs.embarcadero.com/abauer/2008/01/24/38852

请注意,该指令启用加法算术运算符和数组索引运算符 []。

因此,如果启用指针算术,则可以对除无类型指针以外的所有指针执行算术运算。否则仅支持指向字符类型的指针或指向字节的指针。

话虽如此,如果您改为编写 P[1],您的代码会更简洁。显然,这需要启用指针算法。

【讨论】:

    【解决方案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;
    

    您需要使用@Scores[0] 来获取数组中的第一个元素。要获取数组中的下一个整数,您需要添加 SizeOf(Integer) 而不是 1

    【讨论】:

    • Delphi 中的 UINT 是 LongWord(总是 32 位)。这意味着此代码在 x64 模式下无效。问题本身很奇怪,因为它似乎没用。指向数组的指针提供了更简单的语法来访问指向的项目数组(在这种情况下,您将无法执行转换指针-整数-指针的此类错误)。
    • @changyu 可能是 Char 'a' 只有 1 个字节?
    • @user2819514 我正在使用 64 位系统。Sizeof(char) 是 2 个字节。
    【解决方案3】:

    ((Pointer)(P)+1)^ 可以使用 P[1] 代替。

    你可以重写你的代码

    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;
    

    这里不需要指针算法(让编译器为你做他的工作)。

    【讨论】:

    • @David:是的,你说得对,但它默认启用(至少对于 XE3)而且我总是使用“p[i] and p.field”语法而不是“p^[i ] 和 p^.field" 用于指向数组/结构的指针,它使代码更具可读性。
    • @David 我确定默认情况下允许使用 p[i]/p.f 语法而不是 p^[i]/p^.f,但我不确定它是否受到控制通过pointermath指令(实际上我认为它独立于该指令)。
    • 实际上我误读了您的答案,因为我认为您在谈论指针算术。所以,你说得对,这个答案与指针运算无关。我将删除我上面的​​ cmets,但我确实觉得你的回答过于宽泛,并没有解决所提出的实际问题。
    • @David 你又说对了 :) 我试图让家伙远离黑暗面。无论如何,我将您的答案标记为有用。
    • 其实我觉得PIntegerList是阴暗面。这当然是个人品味的问题,显然你和我的不同。但是在我看来,指向一个尽可能大的数组的指针只是一个糟糕的解决方法,因为它缺少指针算法。如果要进行非范围检查的数组访问,请使用指针算法。
    猜你喜欢
    • 2015-01-30
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 2012-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-20
    相关资源
    最近更新 更多