2010-09-23 16 views
11

Estaba viendo Delphi: array of Char and TCharArray "Incompatible Types" y comencé a experimentar. Lo que descubrí es bastante interesante.¿Se permite una matriz dinámica de Char cuando el tipo de parámetro es una matriz abierta de 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. 

Este pequeño ejemplo sencillo muestra cómo se puede pasar una matriz dinámica a un procedimiento usando un parámetro Abrir matriz. Se compila y se ejecuta exactamente como se esperaba.

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. 

Aquí es código casi idéntica la única diferencia de que está utilizando una gran variedad de Char en lugar de Integer. No compila En cambio, el compilador escupe:

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

¿Por qué sería esto?

Después de buscar por un tiempo descubrí this informe de control de calidad. Estoy ejecutando Delphi 2009 y todavía está sucediendo.

+0

¿Qué es "como se espera"? La matriz no se borra en el primer caso. –

+0

Aún así, +1, para solo uno de los casos compila (incluso si usamos 'AnsiChar'), que es bastante extraño, ya que hay muy poca diferencia entre un entero y un' AnsiChar'. –

+0

@Andreas, Ok, me tienes allí. Una matriz vacía no tiene nada que borrar. Mi código de prueba tenía una llamada a SetLength, pero la eliminé porque no era directamente relevante para el error de compilación. –

Respuesta

4

Desde la documentación menciona específicamente parámetros de matriz abierta de tipo char para ser compatible con matrices dinámicas, esto debe ser un error. De 'Open Array Parameters':

function Find(A: array of Char): Integer;
[...]
Nota: [...] El ejemplo anterior crea una función que toma cualquier matriz de elementos de Char, incluyendo (pero no limitado a) dinámicas matrices. [...]

2

Creo que la razón es que es compatible con array of CharPChar, ya que este código se compila:

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. 

Eso es probablemente por razones históricas.
Esperemos que Barry Kelly o Danny Thorpe entren en acción y proporcionen más comentarios al respecto.

--jeroen

+0

¿Cómo sabe 'P' de' MyArray'? No hagas trampas con punteros! ;-) – splash

+3

Mientras se compila, en realidad no funciona. El procedimiento no tiene ni idea de cuál es el límite alto del PChar. –

+0

@Sertac: estoy totalmente de acuerdo en que es un error en alguna parte; solo quería señalar de dónde podría venir. Con suerte, Barry o Danny arrojarán algo de luz aquí. –

4

se puede trabajar con este tipo de matriz, la definición de su propio 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; 

Este código se compilará bien. Por supuesto, no hace nada útil (el parámetro AArray no está configurado como "var", por lo que se copia en la pila antes de asignar un # 0 a cada elemento). Pero al menos, compila.

En la práctica, descubrí que es más fácil definir o usar tipos de alto nivel para matrices dinámicas (como TIntegerDynArray), porque al menos le permite pasar la matriz como referencia, usando una var, evitando así hacer una copia en la pila, y hacer su código más rápido.

Sobre la asignación a un PChar, es habitual para todas las matrices dinámicas: puede asignar una TIntegerDynArray a un puntero, luego usarlo como un PInteger o una 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. 

El problema es la "matriz de "error de código de char" inconsistente con "array of integer" está ciertamente en los intrínsecos del compilador, y el hecho de que un PChar se puede convertir en una cadena.

Cuestiones relacionadas