Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 510
Kendra Lynne Avatar asked Jun 17 '13 17:06

Kendra Lynne


1 Answers

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];
like image 149
Arnaud Bouchez Avatar answered Nov 15 '22 11:11

Arnaud Bouchez