Delphi: toutes les constantes sont constantes, mais certaines sont plus constantes que d'autres?

Considérez:

const 
   clHotlight: TColor = $00FF9933;
   clLink = clHotLight; //alias of clHotlight

[Error] file.pas: Constant expression expected

Et le libellé alternatif qui fonctionne:

const 
   clHotlight = TColor($00FF9933);
   clLink = clHotLight; //alias of clHotlight

Expliquez.


Considérons alors:

const 
   AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
   SuperuserGUID = AdministratorGUID; //alias of AdministratorGUID

[Error] file.pas: Constant expression expected

Et fixer.

Edit: mot-clé ajouté const avant les déclarations; quelqu'un ne croyait pas qu'ils étaient const.

22
demandé sur Ian Boyd 2010-04-26 18:47:14

7 réponses

clHotlight: TColor = $00FF9933; n'est pas une constante mais une constante typée (=variable statique), c'est-à-dire que le compilateur réserve un slot en mémoire pour un TColor qui contiendra la valeur $00FF9933 initialement au moment de l'exécution.
Comme cette valeur peut être modifiée plus tard (avec L'option Const Assignable activée), elle n'est pas une constante réelle et ne peut pas être acceptée par le compilateur dans clLink = clHotLight;

clHotlight = TColor($00FF9933); est strictement la même que clHotlight = $00FF9933;
C'est une vraie constante et le compilateur remplacera clHotlight par sa valeur $00FF9933 partout où il apparaît dans le code. Et pour clLink aussi.

Lire sur cette question SO (dans Delphi 7, Pourquoi puis-je attribuer une valeur à un const?) et toutes les bonnes réponses...

EDIT: à propos de TGUID...
Le problème est que l'écriture AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}'; n'est pas correcte.
Il utilise de la magie du compilateur pour appeler StringToGUID derrière la scène, ce qui permet d'exprimer le GUID sous forme de chaîne ce qu'ils ne sont pas par nature. Ils sont les dossiers.

Donc, essayer {[11] } ne fonctionnera pas. Ce N'est pas un GUID...

Une solution de contournement est d'avoir typé constante et variables pointant vers la même zone de mémoire à l'aide de la absolute directive:

const
   AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
var
   SuperuserGUID: TGUID absolute AdministratorGUID; //alias of AdministratorGUID
   RootGUID: TGUID absolute AdministratorGUID;      //alias of AdministratorGUID
23
répondu François 2017-05-23 12:06:44

J'ai essayé ce code :

  const
    CAnswer1 = 42;
    CAnswer2 : Integer = 42;

  var
    LAnswer : Integer;

  begin
    LAnswer := CAnswer1;
    LAnswer := CAnswer2;
  end;

Et voici le code produit:

Project9.dpr.18: LAnswer := CAnswer1;
004101AC C7056C6E41002A00 mov [$00416e6c],$0000002a //<- assign a hard-coded "42" value
Project9.dpr.19: LAnswer := CAnswer2;
004101B6 A1701C4100       mov eax,[$00411c70] //<- fetch a variable's content
004101BB A36C6E4100       mov [$00416e6c],eax //<- assign this content 

Vous avez raison: certaines constantes sont plus constantes que d'autres. La deuxième constante est en fait traitée par le compilateur comme une variable.

7
répondu LeGEC 2010-04-26 16:13:17
clHotlight: TColor = $00FF9933; 
          ^

Déclare clHotlight en tant que 'variable '(Eh bien, ok une 'constante assignable' si vous l'avez autorisé dans les options du compilateur) au moyen du :.

Comme vous l'avez trouvé, déclarant:

clHotlight = TColor($00FF9933); 

Ne fait aucune allocation de clHotlight jusqu'à ce qu'elle soit spécifiée plus tard.

La même chose s'applique à votre GUID.

5
répondu Brian Frost 2010-04-26 21:13:45

Le problème se pose parce qu'une constante typée n'est pas, vraiment, une constante, comme cela a été expliqué avec plus ou moins de clarté et de succès par d'autres.

Ce qui n'a pas encore été montré, c'est comment contourner le problème (dans un grand nombre de cas), bien qu'un couple ait failli abandonner ce secret... :)

Dans votre cas spécifique, vous pouvez contourner le problème en inversant le "aliasing" de la valeur et la déclaration de constante typée comme suit:

const
  clLink = $00FF9933;
  clHotlight: TColor = clLink;

ClLink fournit maintenant votre véritable constante et clHotlight est typé constante qui a la même valeur que clLink.

Pour les GUID, la même technique peut être utilisée, mais vous devez garder à l'esprit l'expression constante normale utilisée pour initialiser une constante GUID typée - elle n'utilise pas un enregistrement mais une simple chaîne littérale, donc:

const
  ID_CONSTANT = '{AA1C8AF2-C290-40AB-9CF5-2888A46E1660}';
  GUID_CONSTANT: TGUID = ID_CONSTANT;

NOTE: {[10] } de telles constantes GUID sont parfaitement utilisables dans tous les endroits où TGUID sont obligatoires, par exemple IsEqualGUID (tguid, GUID_CONSTANT ) etc.

4
répondu Deltics 2010-04-27 03:13:11
3
répondu Mohammed Nasman 2010-04-26 15:00:51

Le côté droit d'une déclaration de constante doit être une "expression constante", qui est définie comme "une expression constante est une expression que le compilateur peut évaluer sans exécuter le programme dans lequel elle se produit". Vous pouvez trouver toute la syntaxe acceptée pour l'expression constante dans le guide de langue. Notez que le guide de langue indique explicitement "les constantes typées ne peuvent pas se produire dans les expressions constantes."- et c'est pourquoi vos déclarations échoue, à la fois clHotlight: TColor = $ 00FF9933; et AdministratorGUID: TGUID =...; sont des constantes typées. En outre, l'expression constante ne peut pas inclure les appels de fonctions à l'exception de ceux listés dans le guide de langue (C'est-à-dire Length(), SizeOf () et quelques autres) que le compilateur est capable de calculer au moment de la compilation. Réécrire de cette façon:

const
  AdminGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
  AdministratorGUID: TGUID = AdminGUID;
  SuperuserGUID: TGUID = AdminGUID;

Et ça va marcher.

2
répondu 2010-04-27 07:38:27

Bienvenue à Delphes évolution. dans delphi 1 & 2, vous ne pouvez pas attribuer une valeur constante initiale à une var globale (ex: var xVar: Integer = 1). La seule façon de le faire est d'utiliser const xVar: Integer = 1) et certains où dans vos codes, vous pouvez ensuite le changer en somethingelse si vous le souhaitez. Jusqu'à ce qu'ils se débarrassent de cette fonctionnalité ancienne, vous ne pouvez pas utiliser la construction "const xVar: Integer" comme valeur const.

Santé Un Pham

1
répondu APZ28 2010-04-26 19:13:32