Delphi:所有常量都是常数,但有些常数比其他常量更常量?

时间:2010-04-26 14:47:14

标签: delphi constants compiler-errors delphi-5 compiler-constants

考虑:

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

[Error] file.pas: Constant expression expected

和替代措辞有效:

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

解释


然后考虑:

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

[Error] file.pas: Constant expression expected

并修复。

编辑:在声明之前添加关键字const;有人不相信他们是常数。

7 个答案:

答案 0 :(得分:23)

clHotlight: TColor = $00FF9933;不是常量而是类型常量(=静态变量),即编译器在内存中为TColor保留一个插槽,该插槽最初将在运行时保存值$00FF9933。 /> 因为稍后可以更改该值(使用Assignable Const选项为ON),它不是真正的常量,并且clLink = clHotLight;

中的编译器无法接受

clHotlight = TColor($00FF9933);clHotlight = $00FF9933;严格相同 它是一个真正的常量,编译器会将clHotlight替换为值$00FF9933,无论它出现在代码中的哪个位置。对于clLink也是如此。

阅读这个SO问题(In Delphi 7, why can I assign a value to a const?)以及那里的所有好答案......

编辑:关于TGUID ......
问题是写AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';是不合适的 它正在使用一些编译器魔法来调用场景后面的StringToGUID,这样可以方便地将GUID表示为字符串,而这些字符串本质上不是。他们是记录。

因此,尝试AdministratorGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';将无效。那不是GUID ......

解决方法是使用 absolute 指令将类型常量变量指向同一内存区域:< / p>

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

答案 1 :(得分:7)

我试过这段代码:

  const
    CAnswer1 = 42;
    CAnswer2 : Integer = 42;

  var
    LAnswer : Integer;

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

这是生成的代码:

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 

你是对的:一些常数比其他常数更稳定。 第二个常量实际上被编译器视为变量。

答案 2 :(得分:5)

clHotlight: TColor = $00FF9933; 
          ^

通过clHotlight:声明为'变量'(好吧,如果您已在编译器选项中允许,则可以使用'可分配常量') 。

如你所见,宣布:

clHotlight = TColor($00FF9933); 

clHotlight之前未指定之前不进行分配。

这同样适用于您的GUID。

答案 3 :(得分:4)

问题的出现是因为类型常量并非真正的常数,正如其他人所说的不同程度的清晰度和成功所解释的那样。

尚未展示的是如何解决这个问题(在很多情况下),尽管一对夫妇非常接近放弃这个秘密......:)

在您的具体情况下,您可以通过反转值的“别名”和类型化的常量声明来解决问题,如下所示:

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

clLink 现在提供您的真实常量, clHotlight 是与 clLink 具有相同值的类型常量。

对于GUID,可以使用相同的技术,但是你必须记住用于初始化类型化GUID常量的常规常量表达式 - 它不使用记录而是使用简单的文字字符串,因此:

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

注意:此类GUID常量完全适用于需要 TGUID 的所有地方,例如: IsEqualGUID (tguid,GUID_CONSTANT)等。

答案 4 :(得分:3)

答案 5 :(得分:2)

常量声明的右侧必须是“常量表达式”,它定义为“常量表达式是编译器可以在不执行其出现的程序的情况下进行求值的表达式”。您可以在语言指南中找到用于常量表达的完整语法。 请注意,语言指南明确指出“类型常量不能出现在常量表达式中”。 - 这就是你的声明失败的原因,clHotlight:TColor = $ 00FF9933;和AdministratorGUID:TGUID = ...;是类型常量。 此外,常量表达式不能包括函数调用,除了语言指南中列出的函数调用(即Length(),SizeOf()和其他一些函数),编译器能够在编译时计算它们。 用这种方式改写:

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

它会起作用。

答案 6 :(得分:1)

欢迎来到Delphi的演变。在德尔福1&amp; 2,您不能将初始常量值分配给全局变量(例如:var xVar:Integer = 1)。唯一可以做到这一点的方法是使用const xVar:Integer = 1)以及编码中的某些内容,然后根据需要将其更改为somethingelse。在他们摆脱这个古老的特征之前,你不能使用“const xVar:Integer”构造作为const值。

干杯 Pham