5

上記のトピックが示すように、データを順次処理するときに関数 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 ミリ秒遅くなります。

この方法でポインタの処理を効率的に処理する別の方法はありますか、それともクリーンで時間効率の悪い方法ではない方法がありますか?

4

2 に答える 2

9

ここのコードは基本的に問題ありません。私は常に、偽の配列にキャストするよりもポインターをインクリメントすることを選択します。

ただし、整数にキャストしないでください。これは意味的に間違っており、整数サイズとは異なるポインター サイズを持つプラットフォームでコンパイルするたびにペナルティを支払うことになります。正しいサイズの要素へのポインタを常に使用してください。この場合、バイトへのポインター。

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 パラメーターを使用します。

于 2012-12-21T21:44:37.070 に答える
2

私は別の意見を持っています: 読みやすくするために、配列を使用します。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;
于 2012-12-22T10:29:28.863 に答える