2010-09-23 8 views
11

Stavo guardando Delphi: array of Char and TCharArray "Incompatible Types" e ho iniziato a sperimentare. Quello che ho scoperto è piuttosto interessante.È una matrice dinamica di Char consentita quando il tipo di parametro è aperto array di 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. 

Questo semplice esempio mostra come passare una matrice dinamica a una procedura utilizzando un parametro Open Array. Compila e funziona esattamente come previsto.

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. 

Ecco codice quasi identico con la sola differenza che utilizza una matrice di Char anziché Integer. Non viene compilato. Invece il compilatore sputa:

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

Perché dovrebbe essere?

Dopo aver cercato per un po 'ho scoperto il rapporto QC this. Sto gestendo Delphi 2009 e sta ancora accadendo.

+0

Che cosa è "come previsto"? L'array non viene cancellato nel primo caso. –

+0

Ancora, +1, perché solo uno dei casi esegue la compilazione (anche se usiamo 'AnsiChar'), il che è piuttosto strano, poiché c'è una minima differenza tra un intero e un' AnsiChar'. –

+0

@Andreas, Ok, mi hai portato li '. Un array vuoto non ha nulla da chiarire. Il mio codice di test ha ricevuto una chiamata a SetLength ma l'ho rimosso poiché non era direttamente rilevante per l'errore di compilazione. –

risposta

4

Poiché la documentazione menziona specificamente parametri array aperti di tipo char per essere compatibile con gli array dinamici, questo dovrebbe essere un problema. Da 'Open Array Parameters':

function Find(A: array of Char): Integer;
[...]
Nota: [...] L'esempio precedente crea una funzione che prende qualsiasi array di elementi Char, inclusi (ma non limitati a) dinamici array. [...]

2

Penso che il motivo è che array of Char è compatibile con PChar, in quanto questo codice fa compilare:

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. 

che probabilmente è per ragioni storiche.
Si spera che Barry Kelly o Danny Thorpe si avviino e forniscano ulteriori commenti su questo.

--jeroen

+0

Come sa 'P' da' MyArray'? Non barare con i puntatori! ;-) – splash

+3

Mentre compila, in realtà non funziona. La procedura non ha idea di cosa sia il limite superiore del PChar. –

+0

@Sertac: Sono completamente d'accordo che si tratti di un bug da qualche parte; volevo solo indicare da dove potrebbe venire. Spero che Barry o Danny facciano luce qui. –

4

È possibile lavorare con questo tipo di matrice, che definisce il proprio tipo:

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; 

Questo codice verrà compilato bene. Ovviamente non fa nulla di utile (il parametro AArray non è impostato come "var", quindi viene copiato nello stack prima di assegnare un # 0 a ogni elemento). Ma almeno, compila.

In pratica, ho scoperto più facile definire o utilizzare tipi di alto livello per array dinamici (come TIntegerDynArray), perché almeno consente di passare l'array come riferimento, utilizzando una var, evitando così di fare una copia sullo stack e rendere il tuo codice più veloce.

Circa la mappatura a un PChar, è usuale per tutti gli array dinamici: è possibile associare un TIntegerDynArray a un puntatore, quindi utilizzarlo come un PInteger o un 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. 

Il problema è la "matrice di char "codice essendo incoerente con" array of integer "è certamente in intrinseco del compilatore, e il fatto che un PChar può essere castato in una stringa.

Problemi correlati