2009. szeptember 21., hétfő

How to pass multidimensional arrays as parameters to a function or procedure


Problem/Question/Abstract:

How to pass multidimensional arrays as parameters to a function or procedure

Answer:

Passing an array to a procedure or function is straight forward and behaves as expected. However, passing a multi-dimensional array to a function or procedure is not handled in the same way. Consider MyArray to be defined as:


var
  MyArray: array[1..3, 1..5] of double;


And you want to pass it to a procedure called DoSomeThing() defined as:


procedure DoSomeThing(MyArray: array of double);
begin
  showmessage(floattostr(MyArray[1, 1]));
end;


One might think a simple statement like DoSomeThing(MyArray); would do the trick. Unfortunately, this is not the case. The statement DoSomeThing(MyArray); will not compile. The compiler sees the two data structures involved as different types - so it will not allow the statement. The DoSomeThing() procedure is expecting an array of doubles, but the example is passing a multi-dimensional array.

Delphi handles multi-dimensional arrays as user defined type, so there is no syntax to tell a procedure that its parameter(s) are multi-dimensional arrays - without declaring a type. Creating a type, and using this type as the parameter is the correct method to pass a multi-dimensional array. We could just pass a pointer to the array, but inside the function, we need to typecast that pointer. What type to cast it as is the next issue. You would have to have the type defined, or declared identically in 2 places. This method just doesn't make sense.

By defining a type, we can change the process to this:


type
  TMyArray = array[1..3, 1..5] of double;

var
  MyArray: TMyArray;

procedure DoSomeThing(MyArray: TMyArray);
begin
  showmessage(floattostr(MyArray[1, 1]));
end;


Now the actual call looks as we expected:


DoSomeThing(MyArray);


If you want to use the method of passing a pointer, your function might look like this:


type
  PMyArray = ^TMyArray;
  TMyArray = array[1..3, 1..5] of double;

var
  MyArray: TMyArray;

procedure DoSomeThing(MyArray: PMyArray);
begin
  showmessage(floattostr((MyArray[2, 3])));
end;


Note, under 32 bit version Delphi, you do not need to dereference the MyArray variable inside DoSomeThing(). Under older versions you might have to refer to MyArray as MyArray^.

If you want to pass just a generic pointer, you may not be able to use it directly. You can declare a local variable, and use it. Again, you may need to cast the local variable for older versions of PASCAL. Of course this method does offer more flexibility in data usage.


procedure DoSomeThing(MyArray: pointer);
var
  t: ^TMyArray;
begin
  t := MyArray;
  ShowMessage(FloatToStr(t[2, 3]));
end;


Regardless, both calls that use a pointer method, will look something like:


MyArray[2, 3] := 5.6;
DoSomeThing(@MyArray);

Nincsenek megjegyzések:

Megjegyzés küldése