运行时具有负索引的数组

时间:2016-03-17 20:49:02

标签: arrays delphi

我有点卡住了。我想要一个像这样的数组:

Array [-3..Index, 1..otherIndex] of Integer;

但是我还需要根据给定的参数在运行时初始化这个数组。 因此,IndexotherIndex未设置为开始。

我认为我无法在动态数组中初始化负索引但是如何在运行时初始化这样的静态数组呢?

2 个答案:

答案 0 :(得分:4)

将数组包装在记录中。

type
  TMyArray = record
  private 
    FData: array of integer;
    .....
  public
    class function New(Size1, Size2: cardinal): TMyArray; static;
    function Free;  //only needed if you utilize GetMem.
    property Item[x, y: integer]: integer read GetItem write SetItem; default;
  end;

New函数中,您使用SetLength来初始化数组 SetLength(Result.FData, SizeX*SizeY)

GetItem / SetItem对中,您从x索引中添加3到y索引/减1,从而访问从0开始的实数数组。 / p>

<强> GetMem例程
另一种方法是使用GetMem分配一块内存 请注意,GetMem 不会将其内存归零,因此如果要对阵列进行零初始化,则必须调用ZeroMemory来清理缓冲区。 GetItem然后看起来像:

{$pointermath on}

TMyArray = record
private
  FData: PInteger;
  FSizeX, FSizeY: cardinal; //The size of the array.
  .....

//You can use the same code for dynarray and GetMem.
function TMyArray.GetItem(x,y: integer): integer;
begin
  //Inc(x,3); Dec(y,1);
  Result := FData[(x+3)+(y-1)*FSizeX];
end;

由于Item是默认属性,因此您只需编写i := MyArray[-3,2];

即可

<强>清理
如果你使用动态数组,当记录超出范围时,Delphi会自动为你清理内存 如果您使用GetMem,则必须自行清理。

但是,您可以使用记录技巧中的界面添加自动清理/析构函数,请参阅herehere

答案 1 :(得分:0)

如果您有下限(例如-high(smallint)),您可以执行以下操作:

type
  TNegIntArr = Array[-High(SmallInt)..High(SmallInt)] of Integer;
  PNegIntArr = ^TNegIntArr;


procedure use(numNeg : integer; arrLen : integer);
var buf : TIntegerDynArray;
    arr : PNegIntArr ; 
begin
     SetLength(buf, arrLen);
     arr := @buf[numNeg];

     dec(PByte(arr), Cardinal(@arr ^[0]) - Cardinal(@arr^[Low(TNegIntArr)]);

     // you can now savely access the array:
     for counter := -numNeg to arrLen - numNeg - 1 do
         arr^[counter] := counter;
end;

从计算的角度来看,这是非常优化的(没有过程调用),但由于没有启用范围检查,因此也有点危险。