Est-ce un tableau dynamique de Char autorisé lorsque le type de paramètre est un tableau ouvert de Char?
-
04-10-2019 - |
Question
je regardais Delphi: tableau de char et TCharArray "Types incompatibles" et a commencé à expérimenter. Ce que je découvre est assez intéressant.
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.
Ce petit exemple simple montre comment vous pouvez passer un tableau dynamique à une procédure à l'aide d'un paramètre tableau ouvert. Il compile et fonctionne exactement comme prévu.
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.
Voici le code presque identique à la seule différence qu'il utilise un tableau de Char
plutôt que Integer
. Il ne compile pas. Au lieu de cela le compilateur recrache:
E2010 Incompatible types: 'Array' and 'Dynamic array'
Pourquoi serait-ce?
Après avoir cherché pendant un certain temps que je découvre ce rapport de QC. Je suis en cours d'exécution Delphi 2009 et sa passe encore.
La solution
Étant donné que la documentation mentionne spécifiquement les paramètres tableau ouvert de type Char compatible avec les tableaux de dynamiques, cela devrait être un bug. De 'Paramètres tableau ouvert' :
function Find(A: array of Char):
Entier;
[...]
Note: [...] Le exemple précédent crée une fonction qui prend toute matrice d'éléments Char, y compris (mais sans s'y limiter) dynamique tableaux. [...]
Autres conseils
Vous pouvez travailler avec ce genre de tableau, définir votre propre type:
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;
Ce code compilera bien. Il ne fait rien d'utile bien sûr (le paramètre AArray est pas défini comme « var », il est donc copié sur la pile avant d'attribuer un # 0 à chaque article). Mais au moins, il compile.
Dans la pratique, j'ai trouvé plus facile à définir ou à l'utilisation de haut niveau des types de tableaux dynamiques (comme TIntegerDynArray), parce qu'au moins il vous permet de passer le tableau comme référence, en utilisant un var, évitant ainsi de faire un copier sur la pile, et rendre votre code plus rapide.
A propos de la mise en correspondance PChar, il est habituel pour tous les tableaux dynamiques: vous pouvez mapper un TIntegerDynArray à un pointeur, puis utilisez comme un PInteger ou 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.
Le problème est le code beeing incompatible « tableau de char » par « réseau de nombre entier » est certainement dans intrinsèques du compilateur, et le fait qu'un PChar peut être de type coulé à une chaîne.
Je pense que la raison est que array of Char
est compatible avec PChar
, car ce code ne compile:
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.
C'est probablement pour des raisons historiques.
Espérons que Barry Kelly ou Danny Thorpe donnera le coup et donner un peu plus des commentaires à ce sujet.
- jeroen