Search code examples
delphidelphi-xe3

Delphi Array Initializations


This is somewhat a continuation of my previous question, found here. Essentially, I'm trying to test the dll/functions with a basic example, but I'm getting 'E2010 - incompatible types: AInteger/ADouble and Set' and 'E1012 - constant expression violates subrange bounds' errors on my arrays. I get (somewhat) what it's trying to say, but can't figure out what I should be fixing. For example:

var
  n: Integer; 
  Ap, Ai: AInteger;
  Ax, b: ADouble;

begin
  // Initializations
  n := 5;
  Ap := [0, 2, 5, 9, 10, 12]; <- E2010
  Ai := [0, 1, 0, 2, 4, 1, 2, 3, 4, 2, 1, 4]; <- E2010
  Ax := [2, 3, 3, -1, 4, 4, -3, 1, 2, 2, 6, 1]; <- E2010 and E1012
  b := [8, 45, -3, 3, 19]; <- E1012

where the AInteger and ADouble types are my arrays:

ADouble = array[0..High(Integer) div SizeOf(Double) - 1] of Double;
AInteger = array[0..High(Integer) div SizeOf(Integer) - 1] of Integer;

and should be initialized this way (according to Rudy's Delphi page and other C-to-Pascal sources) since they were written as double Ax[] in C. I'm sure there's something simple I'm doing wrong or can change for the sake of testing my dll, but maybe I'm googling wrong because I can't find an example/solution. So, in question form:

Q1: Is E1012 referring to

"And if you do things like these [AInteger and ADouble], be sure not to come too close to High(Integer), since the compiler might complain that the data structure would be too large." (quoted from Rudy's page)

Q2: How should I change this code?

Thanks in advance for any help.


Solution

  • You can do this with such a syntax.

    Defining your array as such:

    ADouble = array[0..High(Integer) div SizeOf(Double) - 1] of Double;
    

    will initialize an array of integer of the size of the whole 32 bit RAM! You will never be able to allocate such a variable (only on Win64, but you will use 4 GB of RAM for storing only 6 integers)! :)

    Your array needs to be dynamic, i.e. to have a changing size at runtime. So you have to define it as such:

    type
      AInteger =  array of integer;
    

    Such arrays can't be assigned directly, in the current state of the language, AFAIR.

    So you need to write such a function:

    procedure SetArray(var dest: AInteger; const values: array of integer);
    begin
      SetLength(dest,Length(values));
      move(values[0],dest[0],length(values)*sizeof(integer));
    end;
    

    And you can use either a constant array as source:

    const
      C: array[0..5] of Integer = (0, 2, 5, 9, 10, 12);
    var
      Ap: AInteger;
    begin
      SetArray(Ap,C);
    

    Or use an open-array parameter:

    var
      Ai: AInteger;
    begin
      SetArray(Ai,[0, 2, 5, 9, 10, 12]);
    

    Of course, the 2nd solution sounds closer to what you expect.

    Update: for newer versions, you can of course use a dynamic array constructor, as such:

    var
      Ai: AInteger;
    begin
      Ai := AInteger.Create(0,2,5,9,10,12);
    

    Update 2: since XE7, you can use another cleaner syntax:

    var
      Ai: AInteger;
    begin
      Ai := [0,2,5,9,10,12];