函数参数中的高效指针处理

时间:2012-12-21 21:24:58

标签: delphi pointers

正如上面的主题所示,我想知道在顺序处理数据时是否有一个干净有效的方法来处理函数parms中传递的指针的好例子。我所拥有的是:

function myfunc(inptr: pointer; inptrsize: longint): boolean;
   var
     inproc: pointer;
     i: integer;
   begin
     inproc := inptr;
     for i := 1 to inptrsize do
       begin
         // do stuff against byte data here.
         inc(longint(inproc), 1);
       end;
   end;

我的想法是,不管有多大的数据,我希望它能够处理任何被推送的内容,而不是有限的数据。

现在谈到处理数据时,我已经想出了几种成功的方法。

  1. 将parm指针分配给相同的临时指针,然后使用它们访问每个数据,递增它们以继续。这种方法是最快的,但不是很干净,所有指针增量遍布整个代码。 (这就是我上面所说的)
  2. 将parm指针分配给表示大数组值的指针,然后使用标准表逻辑对其进行递增处理。更清洁,但比#1慢约500毫秒。
  3. 有没有其他方法可以通过这种方式有效地处理处理指针,或者是否有一些我缺少的方法既干净又不缺时?

2 个答案:

答案 0 :(得分:9)

这里的代码基本上没问题。我总是选择增加指针而不是强制转换为假数组。

但是你不应该转换为整数。这在语义上是错误的,只要您在指针大小与整数大小不同的平台上编译,您就会支付罚金。始终使用指向正确大小的元素的指针。在这种情况下,指向byte。

function MyFunc(Data: PByte; Length: Integer): Boolean;
var
  i: Integer;
begin
  for i := 1 to Length do
  begin
    // do stuff against byte data here.
    inc(Data);
  end;
end;

除非编译器的日子非常糟糕,否则您将无法轻易获得比此更好的代码。更重要的是,我认为这种风格实际上相当清晰,易于理解。大部分的清晰度增加都是为了避免投射。始终努力从代码中删除强制转换。

如果要允许传递任何指针类型,则可以这样写:

function MyFunc(P: Pointer; Length: Integer): Boolean;
var
  i: Integer;
  Data: PByte;
begin
  Data := P;
  for i := 1 to Length do
  begin
    // do stuff against byte data here.
    inc(Data);
  end;
end;

或者如果你想避免界面中的指针,那么使用无类型的const参数。

function MyFunc(const Buffer; Length: Integer): Boolean;
var
  i: Integer;
  Data: PByte;
begin
  Data := PByte(@Buffer);
  for i := 1 to Length do
  begin
    // do stuff against byte data here.
    inc(Data);
  end;
end;

如果需要修改缓冲区,请使用var参数。

答案 1 :(得分:2)

我有不同意见:为了便于阅读,我会使用一个数组。 Pascal的设计不能直接访问内存。原始的pascal甚至没有指针算法。

这是我使用数组的方式:

function MyFunc(P: Pointer; Length: Integer): Boolean;
var
  ArrayPtr : PByteArray Absolute P;
  I : Integer;

begin
  For I := 0 to Length-1 do 
    // do stuff against ArrayPtr^[I]
end;

但如果表现很重要,我会像这样写一下

function MyFunc(P: Pointer; Length: Integer): Boolean;
var
  EndOfMemoryBlock: PByte;

begin
  EndOfMemoryBlock := PByte(Int_Ptr(Data)+Length);
  While P<EndOfMemoryBlock Do begin
    // do stuff against byte data here.
    inc(P);
  end;
end;