2010-09-23 12 views
11

Patrzyłem na Delphi: array of Char and TCharArray "Incompatible Types" i zacząłem eksperymentować. To, co odkryłem, jest dość interesujące.Czy tablica dynamiczna Char jest dozwolona, ​​gdy typem parametru jest otwarta tablica Char?

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. 

Ten prosty mały przykład pokazuje, w jaki sposób można przekazać dynamiczną tablicę do procedury za pomocą parametru Open Array. Kompiluje i działa dokładnie zgodnie z oczekiwaniami.

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. 

Tu jest prawie identyczny kod jedyna różnica polega na tym, że wykorzystuje tablicę Char zamiast Integer. To się nie kompiluje. Zamiast tego kompilator wypluwa:

E2010 Incompatible types: 'Array' and 'Dynamic array' 

Dlaczego miałoby to być?

Po pewnym czasie odszukałem raport QC this. Używam Delphi 2009 i nadal się dzieje.

+0

Co to jest "zgodnie z oczekiwaniami"? Tablica nie jest wyczyszczona w pierwszym przypadku. –

+0

Nadal +1, tylko dla jednego z przypadków kompilujemy (nawet jeśli używamy 'AnsiChar'), co jest dość dziwne, ponieważ istnieje bardzo mała różnica między liczbą całkowitą a" AnsiChar ". –

+0

@Andreas, Ok, masz mnie tam. Pusta tablica nie ma nic do wyczyszczenia. Mój kod testowy miał wywołanie SetLength, ale usunąłem go, ponieważ nie był bezpośrednio związany z błędem kompilacji. –

Odpowiedz

4

Ponieważ dokumentacja wyraźnie wymienia otwarte parametry tablicy typu char być zgodne z tablicami dynamicznymi, powinno to być błąd. Od 'Open Array Parameters':

function Find(A: array of Char): Integer;
[...]
Uwaga: [...] Przedmiotem Poprzedni przykład tworzy funkcję które ma żadnego układu elementów char tym (ale nie wyłącznie) dynamicznych tablic. [...]

2

Myślę, że powodem jest to, że array of Char jest kompatybilny z PChar, jak ten kod nie kompilacji:

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. 

To prawdopodobnie ze względów historycznych.
Mam nadzieję, że Barry Kelly lub Danny Thorpe pojawi się i dostarczy więcej informacji na ten temat.

--jeroen

+0

W jaki sposób 'P' wie z' MyArray'? Nie oszukuj ze wskazówkami! ;-) – splash

+3

Podczas kompilacji nie działa. Procedura nie ma pojęcia, co to jest wysokie stężenie PChar. –

+0

@ Sertac: Całkowicie zgadzam się, że to gdzieś błąd; chciałem tylko wskazać, skąd może pochodzić. Mam nadzieję, że Barry lub Danny rzuci trochę światła tutaj. –

4

Można pracować z tego rodzaju tablicy, definiowania własnych typów:

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; 

Ten kod zostanie skompilowany w porządku. Oczywiście nie robi nic użytecznego (parametr AArray nie jest ustawiony jako "var", więc jest kopiowany na stosie przed przypisaniem # 0 do każdego elementu). Ale przynajmniej się kompiluje.

W praktyce odkryłem, że łatwiej jest zdefiniować lub używać typów wysokiego poziomu dla tablic dynamicznych (takich jak TIntegerDynArray), ponieważ przynajmniej pozwala przekazać tablicę jako odniesienie, używając var, unikając w ten sposób tworzenia kopię na stosie i spraw, by kod był szybszy.

O mapowania do PChar, to zwykle dla wszystkich dynamicznych tablic: można zmapować TIntegerDynArray do wskaźnika, a następnie użyć go jako PInteger lub 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. 

Problemem jest „tablica char "kod niezgodny z" tablicą liczb całkowitych "jest z pewnością w samej kompilacji i fakt, że PChar może być odlewane w typie do łańcucha znaków.

Powiązane problemy