Ist ein dynamisches Array von Char erlaubt, wenn der Parametertyp ist offen Array von Char?
-
04-10-2019 - |
Frage
Ich war auf der Suche auf Delphi: Array von Char und TCharArray "Inkompatible Typen" und begann zu experimentieren. Was ich entdeckte, ist ziemlich interessant.
procedure Clear(AArray: array of Integer);
var
I: Integer;
begin
for I := Low(AArray) to High(AArray) do
AArray[I] := 0;
end;
var
MyArray: array of Integer;
begin
Clear(MyArray);
end.
Dieses einfache kleines Beispiel zeigt, wie Sie eine dynamische Array an eine Prozedur übergeben können, ein offenen Array-Parameter verwenden. Es kompiliert und läuft genau wie erwartet.
procedure Clear(AArray: array of Char);
var
I: Integer;
begin
for I := Low(AArray) to High(AArray) do
AArray[I] := #0;
end;
var
MyArray: array of Char;
begin
Clear(MyArray);
end.
Hier ist nahezu identisch Code der einzige Unterschied ist es eine Reihe von Char
verwendet statt Integer
. Es ist nicht zu kompilieren. Stattdessen wird der Compiler spuckt:
E2010 Incompatible types: 'Array' and 'Dynamic array'
Warum sollte das sein?
Nach einer Suche, während ich entdeckte dieser QC Bericht. Ich bin mit Delphi 2009 und seine immer noch geschieht.
Lösung
Da speziell die Dokumentation erwähnt offene Array-Parameter vom Typ Char mit dynamischen Arrays kompatibel zu sein, soll dies ein Fehler sein. Aus 'Open Array Parameter' :
function Find(A: array of Char):
Ganze Zahl; Cover: [...]
Hinweis: [...] Der voriges Beispiel wird eine Funktion dass nimmt jede Anordnung von Elementen Char, einschließlich (aber nicht beschränkt auf) dynamische Arrays. [...]
Andere Tipps
Sie können mit dieser Art von Array arbeiten, Ihre eigene Art definieren:
type
TCharDynArray = array of char;
procedure Clear(AArray: TCharDynArray);
var
I: Integer;
begin
for I := Low(AArray) to High(AArray) do
AArray[I] := #0;
end;
procedure test;
var
MyArray: TCharDynArray;
begin
Clear(MyArray);
end;
Dieser Code wird kompiliert in Ordnung. Es tut nichts nützlich natürlich (der aArray Parameter wird nicht als „var“ gesetzt, so dass es auf dem Stack kopiert wird, bevor ein # 0 zu jedem Elemente zuweisen). Aber zumindest, es kompiliert wird.
In der Praxis fand ich leichter heraus zu definieren oder die Verwendung auf hohe Ebene von Typen für dynamische Arrays (wie TIntegerDynArray), weil es zumindest ermöglicht es Ihnen, das Array als Referenz zu übergeben, ein var daher vermieden werden ein machen kopieren Sie auf dem Stapel, und machen Sie Ihren Code schneller.
Über die Zuordnung zu einem PChar, ist es üblich, für alle dynamischen Arrays: Sie TIntegerDynArray auf einen Zeiger zuordnen können, dann verwenden, als PInteger oder PIntegerArray:
procedure AddInteger(var Values: TIntegerDynArray; Value: integer);
var n: integer;
begin
n := Length(Values);
SetLength(Values,n+1);
Values[n] := Value;
end;
procedure Loop(V: PInteger);
begin
if V<>nil then
while V^<>0 do begin
write(V^,' ');
inc(V); // go to next integer in array
end;
end;
var IntArray: TIntegerDynArray;
begin
Loop(pointer(IntArray)); // will display nothing, since pointer(IntArray)=nil for IntArray=[]
AddInteger(IntArray,2);
AddInteger(IntArray,3);
AddInteger(IntArray,0);
Loop(pointer(IntArray)); // will display '2 3 '
end.
Das Problem ist der "array of char" Code inkonsistent beeing mit "array of integer" ist sicher in Compiler intrinsics, und die Tatsache, dass ein PChar typ gegossen in eine Zeichenfolge sein kann.
Ich denke, der Grund ist, dass array of Char
kompatibel ist mit PChar
, wie dieser Code nicht kompiliert:
procedure Clear(AArray: array of Char);
var
I: Integer;
begin
for I := Low(AArray) to High(AArray) do
AArray[I] := #0;
end;
var
MyArray: array of Char;
P: PChar;
begin
Clear(P^);
end.
Das ist wahrscheinlich aus historischen Gründen.
Hoffentlich Barry Kelly oder Danny Thorpe wird in kicken und etwas mehr Feedback zu diesem Thema geben.
- jeroen