2010-09-23 6 views
3

J'ai rencontré plusieurs fois cette erreur "Types incompatibles" dans le commentaire ci-dessous, et je n'ai jamais été satisfait de la raison pour laquelle cela n'est pas directement supporté dans Delphi 2007:Delphi: tableau de Char et TCharArray "Types Incompatibles"

program Project1; {$APPTYPE CONSOLE} 

type TCharArray = array of Char; 

procedure DoArray(Chars: array of Char); 
begin 
end; 

function ReturnTCharArray: TCharArray; 
var CharArray: TCharArray; 
begin 
    Result := CharArray; 
end; 

begin 
    DoArray(ReturnTCharArray); // [DCC Error] Project1.dpr(18): E2010 Incompatible types: 'Array' and 'TCharArray' 
end. 

Ne devrait-il pas être possible de rendre un type de tableau "aliasé" à un autre type de tableau compatible les uns avec les autres? En supposant que je ne puisse pas changer la déclaration de DoArray (elle fait partie d'une bibliothèque tierce), comment écrire une fonction retournant un tableau de caractères compatible avec le param de DoArray? La simple "fonction ReturnAChar: array of Char;" aboutit à une erreur "Identifier expected but 'ARRAY' trouvé". J'ai même essayé de changer la fonction retournant le tableau à une procédure avec un var "array of Char", mais cela ne permet pas non plus de régler la longueur du param "array of Char" dans la procédure ("L'objet Constant ne peut pas être passé comme paramètre var ").

Répondre

2

Ce n'est pas le cas. Pascal gère les types de tableaux par nom, pas par description, et l'a toujours fait. Pourquoi ne pouvez-vous pas changer la déclaration de DoArray? (Et pourquoi at-il été écrit comme ça en premier lieu?)

+4

+1; droite! (Oh BTW: il y a aussi la chose "tableau ouvert" par opposition à "tableau typé", c'est probablement là que l'Anagoge va se cogner) –

+0

DoArray fait partie d'une bibliothèque tierce que je ne veux pas (et de façon réaliste ne peut pas) éditer.Je peux vous comprendre parfois vouloir le type de sécurité des types par nom, mais cette restriction de la langue est plus ennuyante que utile, pour moi. N'y a-t-il pas un moyen de convaincre Delphi de retourner un "tableau de char" littéral/exact d'une fonction? Cela semble être une requête assez basique. – Anagoge

+1

@Anagoge: Non, il n'y a pas autant que je sache. Je pense que c'est pourquoi ils ont ajouté 'TArray ' dans Delphi 2009. 'TArray ' est défini comme 'array of T', mais comme c'est maintenant un type nommé, il contourne tous ces problèmes. –

4

Lorsque typed @ operator est hors du compilateur ne vérifie pas ce que vous attribuez à un pointeur, de sorte que vous pouvez appeler une procédure avec mauvais paramètres:

program Project1; {$APPTYPE CONSOLE} 

type TCharArray = array of Char; 

procedure DoArray(Chars: array of Char); 
begin 
end; 

function ReturnTCharArray: TCharArray; 
var CharArray: TCharArray; 
begin 
    Result := CharArray; 
end; 

type TFakeDoArray = procedure(Chars: TCharArray); 

var 
    FakeDoArray: TFakeDoArray; 
begin 
    FakeDoArray := @DoArray; 
    FakeDoArray(ReturnTCharArray); 
end. 

Alors que le compilateur ne se plaindra pas, pour la raison même que 'Jeroen' indique dans son commentaire pour Mason's answer, cela ne fonctionnera pas.

Vous pouvez alors essayer de déclarer votre procédure faux compatible avec un avec un paramètre tableau ouvert:

program Project1; {$APPTYPE CONSOLE} 

type TCharArray = array of Char; 

procedure DoArray(Chars: array of Char); 
begin 
end; 

function ReturnTCharArray: TCharArray; 
var CharArray: TCharArray; 
begin 
    Result := CharArray; 
end; 

type 
    TFakeDoArray = procedure(AnArray: Pointer; High: Integer); 

var 
    FakeDoArray: TFakeDoArray; 
    Tmp: TCharArray; 
begin 
    FakeDoArray := @DoArray; 
    Tmp := ReturnTCharArray; 
    FakeDoArray(Tmp, High(Tmp)); 
end. 

Crédits sont Rudy en raison de son great article. Et la documentation pertinente (de Program Control):

Un paramètre tableau ouvert est passé comme deux valeurs 32 bits. La première valeur est un pointeur vers les données de la matrice, et la deuxième valeur est un de moins que le nombre d'éléments dans le tableau.

-1

Un point que je n'ai pas vu encore mentionné est que TCharArray est un type de tableau dynamique, tout est un paramètre tableau ouvert dans

procedure DoArray(Chars: array of Char); 

Chars. Il n'y a pas de syntaxe pour déclarer un paramètre de tableau dynamique. Pour avoir un paramètre de tableau dynamique, il doit être déclaré en tant que type.

type 
    TMyDynArray = array of Integer; 

procedure DoArray(Integers : TMyDynArray); 
+1

Ceci est incorrect. Toute forme de tableau peut être transmise à un paramètre de tableau ouvert. Que le compilateur rejette c'est parce que le compilateur est défectueux. –

+0

Et où dois-je, dans cette réponse, mentionner que les tableaux dynamiques ne peuvent pas être transmis en tant que paramètre tableau ouvert? Je mentionne seulement que 'array of char' en tant que paramètre ne fait pas du paramètre un tableau dynamique mais un tableau ouvert. Et puisque la question se plaint, il ne peut pas utiliser "SetLength" dans la fonction DoArray, cela suggère que ce qu'il veut n'est pas un paramètre tableau ouvert. Et avec le necro? –

5

Ceci peut en fait être un bogue du compilateur (ou une limitation qui n'a jamais été documentée correctement). J'ai fait quelques expérimentations et j'ai trouvé que vous pouviez passer un tableau dynamique (tapé ou non) à une procédure qui attendait un tableau ouvert pour presque tous les types ... sauf Char et WideChar.

Voir Is a dynamic array of Char allowed when the parameter type is open array of Char? pour une description du problème et un possible contourner.

+0

Pour une raison quelconque, j'ai toujours pensé que les tableaux dynamiques et les tableaux ouverts étaient incompatibles ... En fait, je suis assez surpris que seuls Char et Widechar le soient. On dirait qu'ils ont été impliqués dans mes premières expérimentations avec les tableaux Delphi, et je n'y suis jamais retourné. Ou peut-être était-ce dans Delphi 5? –

+0

@Ken La documentation affirme que les paramètres de tableau ouverts peuvent gérer n'importe quel tableau du même type. Donc j'étais tout aussi surpris que le tableau de Char et le tableau de WideChar ne compilent pas. –

+0

@KennethCochran: Il devrait accepter * tout * tableau, même tableau de Char/WideChar. –

Questions connexes