Search code examples
delphidelphi-xe2dynamic-arraysvariant

Do dynamic arrays support a non-zero lower bound (for VarArrayCreate compatibility)?


I'm going maintain and port to Delphi XE2 a bunch of very old Delphi code that is full of VarArrayCreate constructs to fake dynamic arrays having a lower bound that is not zero.

Drawbacks of using Variant types are:

  • quite a bit slower than native arrays (the code does a lot of complex financial calculations, so speed is important)
  • not type safe (especially when by accident a wrong var... constant is used, and the Variant system starts to do unwanted conversions or rounding)

Both could become moot if I could use dynamic arrays.

Good thing about variant arrays is that they can have non-zero lower bounds.

What I recollect is that dynamic arrays used to always start at a lower bound of zero.

Is this still true? In other words: Is it possible to have dynamic arrays start at a different bound than zero?

As an illustration a before/after example for a specific case (single dimensional, but the code is full of multi-dimensional arrays, and besides varDouble, the code also uses various other varXXX data types that TVarData allows to use):

function CalculateVector(aSV: TStrings): Variant;
var
  I: Integer;
begin
  Result := VarArrayCreate([1,aSV.Count-1],varDouble);
  for I := 1 to aSV.Count-1 do
    Result[I] := CalculateItem(aSV, I);
end;

The CalculateItem function returns Double. Bounds are from 1 to aSV.Count-1.

Current replacement is like this, trading the space zeroth element of Result for improved compile time checking:

type
  TVector = array of Double;
function CalculateVector(aSV: TStrings): TVector;
var
  I: Integer;
begin
  SetLength(Result, aSV.Count); // lower bound is zero, we start at 1 so we ignore the zeroth element
  for I := 1 to aSV.Count-1 do
    Result[I] := CalculateItem(aSV, I);
end;

Solution

  • Dynamic arrays always have a lower bound of 0. So, low(A) equals 0 for all dynamic arrays. This is even true for empty dynamic arrays, i.e. nil.

    From the documentation:

    Dynamic arrays are always integer-indexed, always starting from 0.