program arraytest;
uses
SysUtils;
const
Fmt='[0x%p]';
type
TDynamicArray=array of integer;
TStaticArray=array[10..15] of integer;
procedure ProcAddress(P:pointer);
begin
writeln(Format(Fmt,[P]));
end;
procedure ProcStatiConst(const V:TStaticArray);
begin
// V[13]:=0; // Compile error - OK
end;
procedure ProcDynamicConst(const V:TDynamicArray);
begin
writeln('After the call: Array address ',Format(Fmt,[@V]),' Array[0] address ',Format(Fmt,[@(V[0])]),' - Why has V got a new address');
writeln('Length ',Length(V));
writeln('High ',High(V));
writeln('V[0] ',V[0]);
// SetLength(V,3); // Compile error - OK
V[0]:=1111; // Not an error - strange, but somewhat understandable
writeln('Before return: Array address ',Format(Fmt,[@V]),' Array[0] address ',Format(Fmt,[@(V[0])]),' - Value changed in V[0] pointing to the Caller''s area');
end;
procedure ProcDynamicVar(var V:TDynamicArray);
begin
writeln('After the call: Array address ',Format(Fmt,[@V]),' Array[0] address ',Format(Fmt,[@(V[0])]),' - This is OK');
writeln('Length ',Length(V));
writeln('High ',High(V));
writeln('V[1] ',V[1]);
V[1]:=2222;
writeln('After changing V[1], but not the length: Array address ',Format(Fmt,[@V]),' Array[0] address ',Format(Fmt,[@(V[0])]),' - No change in the pointers when only a value changed, OK');
SetLength(V,16);
V[1]:=2345;
writeln('New length ',Length(V));
writeln('Before return (also the length is changed): Array address ',Format(Fmt,[@V]),' Array[0] address ',Format(Fmt,[@(V[0])]),' - New pointer of V[0] as the length also changed, OK');
end;
procedure ProcDynamicValue(V:TDynamicArray);
begin
writeln('After the call: Array address ',Format(Fmt,[@V]),' Array[0] address ',Format(Fmt,[@(V[0])]),' - V has a new address, but V[0] is still the same');
writeln('Length ',Length(V));
writeln('High ',High(V));
writeln('V[2] ',V[2]);
V[2]:=3333; // This is updated in the original memory area
writeln('After changing V[2], but not the length: Array address ',Format(Fmt,[@V]),' Array[0] address ',Format(Fmt,[@(V[0])]),' - Just like for Var, no change in the pointers, so again it wrote to the Caller''s area');
SetLength(V,26);
V[2]:=3456; // This is updated in the new - local use only - memory area
writeln('New length ',Length(V));
writeln('Before return (also the Length is changed): Array address ',Format(Fmt,[@V]),' Array[0] address ',Format(Fmt,[@(V[0])]),' - Now the payload area is updated, but that is not handed back to Caller');
end;
procedure ProcOpenConst(const V:array of integer);
begin
writeln('After the call: Array address ',Format(Fmt,[@V]),' Array[0] address ',Format(Fmt,[@(V[0])]),' - Now even V points to the same as V[0], not an "object"');
writeln('Length ',Length(V));
writeln('High ',High(V));
writeln('V[3] ',V[3]);
// SetLength(V,36); // Compile error - OK, with the expected error message
// V[3]:=4444; // Compile error - Here it notices that it is a const parameter, so why not above
writeln('Before return: Array address ',Format(Fmt,[@V]),' Array[0] address ',Format(Fmt,[@(V[0])]));
end;
procedure ProcOpenVar(var V:array of integer);
begin
writeln('After the call: Array address ',Format(Fmt,[@V]),' Array[0] address ',Format(Fmt,[@(V[0])]),' - Again @V=@V[0]');
writeln('Length ',Length(V));
writeln('High ',High(V));
writeln('V[4] ',V[4]);
// SetLength(V,46); // Compile error with "Type mismatch"?
// writeln('New length ',Length(V));
V[4]:=5555;
writeln('Before return: Array address ',Format(Fmt,[@V]),' Array[0] address ',Format(Fmt,[@(V[0])]));
end;
procedure ProcOpenValue(V:array of integer);
begin
writeln('After the call: Array address ',Format(Fmt,[@V]),' Array[0] address ',Format(Fmt,[@(V[0])]),' - Here even if called with a variable, a new area is allocated - OK');
writeln('Length ',Length(V));
writeln('High ',High(V));
writeln('V[5] ',V[5]);
// SetLength(V,56); // Compile error with "Type mismatch"?
// writeln('New length ',Length(V));
V[5]:=6666;
writeln('Before return: Array address ',Format(Fmt,[@V]),' Array[0] address ',Format(Fmt,[@(V[0])]));
end;
procedure Caller;
var
MyArray:TDynamicArray;
i:integer;
begin
SetLength(MyArray,6);
for i:=0 to 5 do
MyArray[i]:=i+11;
writeln('Versions to call the 6 procedures with a Variable.');
writeln;
writeln('Calling ProcDynamicConst with MyArray address ',Format(Fmt,[@MyArray]),' MyArray[0] address ',Format(Fmt,[@MyArray[0]]));
ProcDynamicConst(MyArray);
writeln('The value is changed. It should not be allowed. ',MyArray[0]);
writeln;
writeln('Calling ProcDynamicVar with MyArray address ',Format(Fmt,[@MyArray]),' MyArray[0] address ',Format(Fmt,[@MyArray[0]]));
ProcDynamicVar(MyArray);
writeln('The value is changed. OK. ',MyArray[1]);
writeln;
writeln('Calling ProcDynamicValue with MyArray address ',Format(Fmt,[@MyArray]),' MyArray[0] address ',Format(Fmt,[@MyArray[0]]));
ProcDynamicValue(MyArray);
writeln('The value is changed as per the first change, but not as per the second. This is clearly wrong! ',MyArray[2]);
writeln;
writeln('Calling ProcOpenConst with MyArray address ',Format(Fmt,[@MyArray]),' MyArray[0] address ',Format(Fmt,[@MyArray[0]]));
ProcOpenConst(MyArray);
writeln('The value is not changed. Already prevented by the Compiler. OK.');
writeln;
writeln('Calling ProcOpenVar with MyArray address ',Format(Fmt,[@MyArray]),' MyArray[0] address ',Format(Fmt,[@MyArray[0]]));
ProcOpenVar(MyArray);
writeln('The value is changed, despite the strange pointer within ProcOpenVar. OK. ',MyArray[4]);
writeln;
writeln('Calling ProcOpenValue with MyArray address ',Format(Fmt,[@MyArray]),' MyArray[0] address ',Format(Fmt,[@MyArray[0]]));
ProcOpenValue(MyArray);
writeln('The value is not changed. OK. ',MyArray[5]);
writeln;
writeln('Versions to call the 6 (actually only 2 of them allowed) procedures with Values');
// ProcDynamicConst([5,10,15,20,25,30]); // Compile error, not necessarily OK
// ProcDynamicVar([5,10,15,20,25,30]); // Compile error, would be OK with "Variable identifier expected", but here the same error is given as previously
// ProcDynamicValue([5,10,15,20,25,30]); // Compile error, not necessarily OK
writeln;
writeln('Calling ProcOpenConst');
ProcOpenConst([5,10,15,20,25,30]);
// ProcOpenVar([5,10,15,20,25,30]); // Compile error with the expected error message ("Variable identifier expected")
writeln;
writeln('Calling ProcOpenValue');
ProcOpenValue([5,10,15,20,25,30]);
end;
begin
Caller;
end.