Board index » delphi » WACKY array indeces! CRAZY!!!

WACKY array indeces! CRAZY!!!

I just wrote a little routing to check the passing of arrays to functions
and their corresponding values.  This may be common knowledge, but it seems
dangerous to me..

Say I have an array of integers, junkarray, dimensioned as:

junkarray: array[1..10] of integer;

And I initialize it by,

        for i := 1 to 10 do junkarray[i] := i;

and check it by,

        ShowMessage(IntToStr(junkarray[1]));

which gives '1', as one would expect.

Then I pass this array to a function:

        function test(const junkarray: Array of Integer): Integer;
        begin
          test := junkarray[1];
        end;

Back in the main routine, I have:

        ShowMessage(IntToStr(test(junkarray)));

Which gives a value of 2!!!!!!!  This means that all of the array indeces
are reset with 0 as the starting index when the array is passed to the
function, even though the initial declaration has the starting index as 1!!
INSANE!

 

Re:WACKY array indeces! CRAZY!!!


This is not so insane, since the array is only passed as a pointer. The
function Test cannot assume anything about the value of the first index,
and therefore it is set to 0.

Regards,
Wouter.

Re:WACKY array indeces! CRAZY!!!


Quote
rwm wrote:
>         function test(const junkarray: Array of Integer): Integer;
>         begin
>           test := junkarray[1];
>         end;

This is dangerous. JunkArray is an open array, and as such, can contain
fewer than two elements. If I passed an array [1..1] of Integer, the
assignment above would cause an AV.

Quote
> This means that all of the array indeces
> are reset with 0 as the starting index when the array is passed to the
> function, even though the initial declaration has the starting index as 1!!
> INSANE!

Open-array parameters are by definition indexed from 0 (it's in the
help). I can't find the specifics of storage anywhere in the help, but I
would imagine that var and const open-array parameters use eight bytes
of the function's stack frame. The first four bytes are probably the
highest element and the next four bytes are the address of the first
element of the array. For value parameters, the entire array is copied
to the stack frame. If you wanted the starting index to be preserved and
not set to zero, the compiler would have to pass an additional four
bytes, something the folks at Inprise decided wasn't worth it. I think
it would be worth it. Or maybe I'm missing something more complicated.
Thoughts, anyone?

You should use High to determine the highest index of the array
available. Low always returns 0 for open-array parameters, but it's good
practice to use Low instead of 0 anyway.

Perhaps you want function Test to only take an array [1..10] of Integer.
If that's the case, define a type first:

type
  TJunkArray = array [1..10] of Integer;

function Test(const JunkArray: TJunkArray): Integer;
begin
  Result := JunkArray[1]; // This is now safe.
end;

If you want to be able to use other arrays in the function, you'll need
to use an open-array parameter like you did. But they always index
starting at 0.

Dave

Re:WACKY array indeces! CRAZY!!!


Quote
rwm wrote:
> Which gives a value of 2!!!!!!!  This means that all of the array indeces
> are reset with 0 as the starting index when the array is passed to the
> function, even though the initial declaration has the starting index as 1!!
> INSANE!

Your are correct, but there's a reason for it, and there's a way around
it.

First the way around it:  Use the functions Low and High rather than
absolute indicies.

Now the reason:  Open arrays (which is what the parameter to test is
called) are generic, in that any array of integer could be passed (for
instance "array[-100001..-100010] of integer" would be just as valid an
argument) To enable a single set of statements to deal with the
unlimited possibilities for arguments, the arrays are "normalized" to a
starting value of 0 (=Low(JunkArray)) and an ending value of
High(JunkArray).  

If you know you're always going to pass an array of [1..10] then you
should make it a type and pass as that type rather than as an open
array.

I hope that explains it.
Bob Lee

Re:WACKY array indeces! CRAZY!!!


Quote
Dave Shapiro wrote:
> I think
> it would be worth it. Or maybe I'm missing something more complicated.
> Thoughts, anyone?

I might argue that it would serve no purpose.  Since no assumptions
could be made about the starting point you'd still always have to use
Low(), Low()+1 etc. so you really haven't gained anything.
Additionally, performance would suffer due to the need to continually
convert the index into a memory offset.  Since the starting value is
arbitrary, might as well make it something useful.

Bob Lee

Other Threads