Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Different Arrays sharing same storage space? 1

Status
Not open for further replies.

HobbyProgrammer

Programmer
Oct 31, 2003
7
TR
Hi

With an ABSOLUTE-declaration it is possible that two different arrays share the some storage space, e.g. like

NumberSequence : Array [0..9] of Integer;
FirstPart : Array [0..4] of Integer ABSOLUTE NumberSequence[0];

Note, both arrays are starting here from zero.

Now, how could it be done if the second array does not start from zero? E.g. with

Thank you
MiddlePart : Array [0..1] of Integer;

to share the storage space of NumberSequence[4] and NumberSequence[5]
 
Hi,

IMHO one should be extremly wary of such an approach. Arrays are stored like strings with reference counting and dynamic memory allocation. By declaring two versions of the same array I would not like to predict what Delphi would do, and how that behaviour might change with future versions.

As an alternative I might use pointers or just copy the part of the array you want. Less efficient I grant you, but much safer.

However, if you come up with a robust solution, do post it. It would be interesting.
 
I must admit that I'm not familiar in using pointers. Do you have a suggestion on how to solve the problem with pointers? Thank you.
 
var
NumberSequence : Array [0..9] of Integer;
pInt : PInteger; {type PInteger=^Integer, defined in VCL somewhere}
i:integer;
begin
for i:=Low(NumberSequence)to High(NumberSequence)do
NumberSequence:=i*11;

pInt:=@NumberSequence[4];
Inc(pInt);
Memo1.Lines.Add(IntToStr(pInt^)); {gives 55}
Inc(pInt,2);
Memo1.Lines.Add(IntToStr(pInt^)); {gives 77}


Does this give you enough clues?
 
Unfotunately there does not seem to be a "reasonable" solution to my problem. Your short course of instruction on pointers is verry helpful. Thank you!
 
I agree with VintageWine in that you should avoid this kind of construct as much as possible. Perhaps you could explain why you feel you need to use it and there might be other ways around it.

Meanwhile you could achieve what you want if you define MiddlePart as follows:
Code:
MiddlePart: Array [-4..5] of Integer ABSOLUTE NumberSequence[0];
Then MiddlePart[0] will be exactly the same location as FirstPart[4] and MiddlePart[1] will be the same as FirstPart[5].

Andrew
 
With all the warnings I received, it seems better to leave this way of solving the problem.

The question arose when trying to pass a part of the following array data into a procedure, e.g. from the array

var Names: Array[0..2,0..100]of String[99];
the part
Names[1,0..100];

If the array would be String without [99], the it would simply mean:

MyProcedure(var AllNames1 : Array of String);
beeing called with
MyProcedure(Names[1]);

I could not find out how to do it with the array of String[99].
My be you have a solution, where I do not have to change this basic array declaration and adjust the whole project.
 
Two ideas.

1. Use copy. Your are probably used to using it with strings, but there is an overloaded version that works with arrays. Check out the help. As noted in my first post, both arrays and strings use dynamic memory allocation, hence the common function.

2. Write an class using pointers to slice up the array. This is more work, but will keep a single copy of the array so changes made in the called function will be reflected back into the original array.

Two health warnings on this class:
- I have just typed it in, not tested it, but I am sure you could get it working.
- I haven't handled multi-dim arrays, but again it would be easy to adapt it to do so.


TStringPointer=^string;

TArraySlice=class(TObject)
private
FBase:TStringPointer;
FLength:integer;
function GetPointer(AIndex:integer):TStringPointer;
function GetItem(AIndex:integer):string;
procedure SetItem(AIndex:integer; AValue:string);
public
constructor Create(AArray:array of string; AStart:ALength:integer)
property Items[Index:integer]:string; default;
end;

constructor TArraySlice.Create(AArray:array of string; AStart:ALength:integer)
begin
if(AStart+ALength>Length(AArray))then
Raise EException.Create('No way');

FBase:=@AArray[AStart];
FLength:=ALength;
end;

function TArraySlice.GetPointer(AIndex:integer):TStringPointer;
begin
if(AIndex>=FLength)then
Raise EException.Create('No way');

Result:=FBase;
Inc(Result,AIndex);
end;

function TArraySlice.GetItem(AIndex:integer):string;
begin
Result:=GetPointer(AIndex)^;
end;

procedure TArraySlice.SetItem(AIndex:integer; AValue:string);
begin
GetPointer^:=AValue;
end;


......... and in your program ...........

procedure()
var
Names:array[0..100]of string;
LArraySlice:TArraySlice;
begin
...
...

LArraySlice:=TArraySlice.Create(Names,10,5);
try
MyProcedure(LArraySlice);
finally
LArraySlice.Free;
end;

...
...
end;


Have fun
Simon
 
Thank you Simon for all your clues to solve the problem. Will try now to get it work.
Greetings Marcel (from some where in the Swiss mountains).
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top