tags:

views:

108

answers:

4

I have a static array:

myArray: array [0..15] of byte;

I wish to pass this array (not a copy of the array) into a function. Inside the function, I will manipulate the data in array.

Different lengths of STATIC byte array may be passed in to Init at different times. Therefore, I do not wish to declare Init to be able to receive only a certain length of byte array. (e.g. in this case it is a 16 bytes. At other times it may be 65000 bytes)

This is the way I used the function:

Init(@myArray[0]); //passing in pointer to static array

I tried to declare Init like this:

procedure Init(x: array of byte);
begin
//Do some stuff with x, for e.g.
Length(x);  //I do not intend to pass in the length as a parameter, 
            //but determine it in this function itself.  


end;

Is this also a correct way of declaring the Init function parameter?

+1  A: 
  1. Instead of Init(@myArray[0]) use Init(myArray). Delphi will transfer the myArray by reference
  2. You declared x as open array of bytes. The open array parameters are type compatible with the array variables with the same element type. Delphi will transfer fixed array length as a hidden parameters.
  3. Open array parameters cannot be set to nil. If you need to set x to nil, then you have to declare x as pointer to Byte or pointer to array[..] of Byte.
da-soft
+1  A: 

first when your are declarating this

procedure Init(x: array of byte);

you are using a dynamic array open array parameter instead of a static array. to pass a static array as a parameter , you must define a type

like this

type
  Arr15      = array [0..15] of byte;

and then declare the procedure like this, using the keyword var to pass by reference.

procedure Init(var x: Arr15);

about the nil assign , you cannot set to nil a static array.

another alternative is use a dynamic array check this sample

type
  ByteArray  = array of byte; 

procedure Init(var x : ByteArray);
const
 LenArray=15;
var
  i       : Byte;
begin
  SetLength(x,LenArray); //alocate the memory and set the length of the array.

  for i:=0 to LenArray-1  do //fill the array
     x[i]:=i;

   Writeln(Length(x)); //show the len of the array
   SetLength(x,0); //now dealocates de memory
   Writeln(Length(x)); //show the len of the array again 
end;

Var
  myArray : ByteArray;
begin
  try
     Init(myArray);
     Readln;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.
RRUZ
Hi...if myArray is static array, how can I still pass it into Init function? I have many different lengths of STATIC array that I need to pass into Init. Therefore, I wish Init is able to receive arrays of different lengths, not just only able to receive a certain length.
seveleven
+4  A: 

First, declaring

procedure Init(x: array of byte);

declare an open array parameter (not a dynamic array, unlike some other stated).

To do what you want, you need to declare like this :

type
  TMyArray: array [0..15] of byte; 
var
  MyArray : TMyArray;

Procedure Init(var X : TMyArray)

Still, I'm not sure why you try to set the variable to nil. A static array variable is a little bit like a record, you can't set it to nil. And IF you pass a pointer to the function instead, you will need to assign your array to a variable first anyway(or allocate the memory directly in the function). Like this :

type
  TMyArray : Array[0..15] of byte;
  pTMyArray : ^TMyArray;

  Procedure Init(var X : pTMyArray);
procedure DoSomething;
var P : pTMyArray;
begin
  New(P); //or if you array is global, simply do "P := @MyArray"
  try
    //code here
    Init(P);
    //code here
  finally
    Dispose(P);
  end;
end

But that would be a bad construct IMO, because if you set your array pointer to nil inside the Init function, you will get a memory leak. So this is pretty bad to start with. But I guess if it's your Init function that reserve the memory that would be OK.

If you settle for an open array parameter, I'd suggest using the Low and High to determine the bounds of the array.

I think that's the best info I can give you until you give more detail on what you are trying to achieve.

EDIT Ok, if you need the function to accept an array of different size, you need an open array parameter.

You did it right in your exemple. But you can't set it to nil within the function.

I don't think it's possible to pass to a function a pointer to an open array type. If you really want a pointer to set it to nil, you will need to pass it as PByteArray... But you will need to also pass the size of the array.

Ken Bourassa
You can zero the contents of the array (if you need to because it's a stack variable) just with for i:=low(X) to high (X) do X[i]:=0 or using the old FillChar (fast but risky if you make a mistake). But you can't set the "pointer to the array" to nil, because you don't control the pointer in the first example. In the second you do, but it's a lot of hassle unless you really, really need it.
moz
Different sizes of byte array may be passed in to the Init function. Thus, I do not want to set the Init to receive only a certain size of array (size 16 in this case). How could I declare Init to receive any array of bytes?
seveleven
+2  A: 

For static arrays there is no information about their length at runtime, but only at compile time.

So if you loose the type information at passing a static array to a function, there is no way to find out the length of the array within the function.

=> If you want to use static arrays with variable sizes, you must pass the size as additional parameter.

The clean way would be to work with pointer aritmetic rather than arrays here.

PByte = ^byte;
procedure Init(arr: PByte; len: Integer);
var
  i: Integer;
begin
  //Write 0, 1, 2 ... to arr
  for i:= 0 to len-1 do 
  begin
    arr^:= i;
    Inc(arr);
  end;
end;

Unclean solution:

TByteArray = array [0..$FFFFFFFF] of Byte;
PByteArray = ^TByteArray;

procedure Init(arr: PByteArray; len: Integer);
begin
  arr^[0]:= 0;
  arr^[1]:= 1;
  ...
end;

...
var
  myAray: array[0..10] of byte;
begin
  Init(PByteArray(@myArray[0]), 10);
end;
nang