Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you pass an array by reference in Delphi?

I already read up about passing by reference and so

procedure test(var x:integer);
begin
  x:=x+5;
end;

so the above code updates 5 by reference. I assumed if I was updating an array by reference I could declare var X: array of blah... having some bound bugs and just wanted to know if I should be using the type of data for the pointer to the data or if the pointer is always int... just so I know if it's how I'm doing my passing by reference or something else in my code that is the issue.

like image 432
Arthur Avatar asked Apr 03 '09 15:04

Arthur


People also ask

How do you pass an array to a function in Delphi?

And you'd have to use 'data^' instead of 'data' everywhere in the method. type TData = array of integer; PData = ^TData; procedure IncArray(data: PData); var i : integer; begin for i := Low(data^) to High(data^) do data^[i] := data^[i] + 5; end; procedure TForm8.

How do you pass by reference in Delphi?

In Delphi to pass by reference you explicitly add the var keyword: procedure myFunc(var mytext:String); This means that myFunc can modify the contents of the string and have the caller see the changes.

How do you pass references to an array?

Arrays can be passed by reference OR by degrading to a pointer. For example, using char arr[1]; foo(char arr[]). , arr degrades to a pointer; while using char arr[1]; foo(char (&arr)[1]) , arr is passed as a reference. It's notable that the former form is often regarded as ill-formed since the dimension is lost.

What does it mean to pass an array by reference?

If we pass the address of an array while calling a function, then this is called function call by reference. The function declaration should have a pointer as a parameter to receive the passed address, when we pass an address as an argument.


1 Answers

If you pass dynamic array as a non-var parameter, compiler will make a copy.

The small code sample below demonstrates that by displaying 37/42 in the form caption.

procedure IncArray1(data: array of integer);
var i : integer;
begin
  for i := Low(data) to High(data) do
    data[i] := data[i] + 5;
end;

procedure IncArray2(var data: array of integer);
var i : integer;
begin
  for i := Low(data) to High(data) do
    data[i] := data[i] + 5;
end;

procedure TForm8.FormCreate(Sender: TObject);
var
  data: array of integer;
begin
  SetLength(data, 1);
  data[0] := 37;
  IncArray1(data);
  Caption := IntToStr(data[0]);
  IncArray2(data);
  Caption := Caption + '/' + IntToStr(data[0]);
end;

If we look into the generated assembler code, IncArray1 starts with

004552B4 8BCA             mov ecx,edx
004552B6 85C9             test ecx,ecx
004552B8 7807             js $004552c1
004552BA 8B1C88           mov ebx,[eax+ecx*4]
004552BD 49               dec ecx
004552BE 53               push ebx
004552BF 79F9             jns $004552ba
004552C1 8BC4             mov eax,esp

This code copies source array to the stack and sets eax to the address of the first element (= address stored in the stack pointer after last push). Stack grows down so the code starts with the last element (edx contains High(data) when IncArray1 is called) and repeats (read element; push element; decrement index) until it gets to the element 0.

IncArray2 contains no such code. Caller stores the address of the data into the eax register before calling IncArray2 and IncArray2 just uses this address.

In case you don't want to use 'var' for any reason, you can pass an address of the data to your method. But as you can't use syntax 'data: ^array of integer' in parameter declaration, you'd have to declare a type for your data. And you'd have to use 'data^' instead of 'data' everywhere in the method.

type
  TData = array of integer;
  PData = ^TData;

procedure IncArray(data: PData);
var i : integer;
begin
  for i := Low(data^) to High(data^) do
    data^[i] := data^[i] + 5;
end;

procedure TForm8.FormCreate(Sender: TObject);
var
  data: TData;
begin
  SetLength(data, 2);
  data[0] := 37;
  IncArray(@data);
  Caption := IntToStr(data[0]);
end;

Tested with Delphi 2007.

like image 62
gabr Avatar answered Oct 30 '22 08:10

gabr