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

发布于 2024-08-30 16:09:57 字数 640 浏览 7 评论 0原文

考虑:

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;有人不相信他们是常量。

Consider:

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

[Error] file.pas: Constant expression expected

and the alternate wording that works:

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

Explain.


Then consider:

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

[Error] file.pas: Constant expression expected

And fix.

Edit: Added keyword const before declarations; someone didn't believe they were const.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

屌丝范 2024-09-06 16:09:57

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

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

阅读这个问题(在 Delphi 7 中,为什么我可以给 const 赋值?)以及那里所有好的答案...

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

因此,尝试 AdministratorGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}'; 将不起作用。这不是 GUID...

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

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

clHotlight: TColor = $00FF9933; is not a constant but a typed constant (=static variable), i.e. the compiler reserves a slot in memory for a TColor which will hold the value $00FF9933 initially at run time.
Because that value can be changed later (with the Assignable Const option ON), it is not a real constant and cannot be accepted by the compiler in clLink = clHotLight;

clHotlight = TColor($00FF9933); is strictly the same as clHotlight = $00FF9933;
It is a true constant and the compiler will replace clHotlight by its value $00FF9933 wherever it appears in the code. And for clLink as well.

Read on this SO question (In Delphi 7, why can I assign a value to a const?) and all the good answers there...

EDIT: about TGUID...
The problem is that writing AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}'; is not proper.
It is using some compiler magic to call StringToGUID behind the scene, allowing the convenience to express the GUID as a string which they are not by nature. They are records.

So, trying AdministratorGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}'; will not work. That is not a GUID...

A workaround is to have a typed constant and variables pointing to the same memory area using the 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
烟酒忠诚 2024-09-06 16:09:57

我尝试了这段代码:

  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 

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

I tried this code :

  const
    CAnswer1 = 42;
    CAnswer2 : Integer = 42;

  var
    LAnswer : Integer;

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

and here is the produced code :

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 

You are right : some constants are more constant than others.
The second constant is actually treated by the compiler as a variable.

夏日落 2024-09-06 16:09:57
clHotlight: TColor = $00FF9933; 
          ^

通过 :< 将 clHotlight 声明为“变量”(好吧,如果您在编译器选项中允许这样做,那么可以是“可分配常量”) /代码>。

正如您所发现的,声明:

clHotlight = TColor($00FF9933); 

不分配 clHotlight,直到稍后指定。

这同样适用于您的 GUID。

clHotlight: TColor = $00FF9933; 
          ^

Is declaring clHotlight as a 'variable' (well, ok an 'assignable constant' if you've permitted this in compiler options) by means of the :.

As you've found, declaring:

clHotlight = TColor($00FF9933); 

Makes no allocation of clHotlight until it is specified later.

The same applies to your GUID.

Hello爱情风 2024-09-06 16:09:57

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

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

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

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

clLink 现在提供真正的常量,clHotlight 是与 clHotlight 具有相同值的类型化常量强>clLink。

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

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

注意:< /strong> 这样的 GUID 常量在所有需要 TGUID 的地方都可以完美使用,例如 IsEqualGUID( tguid, GUID_CONSTANT ) 等。

The problem arises because a typed constant is not, truly, a constant, as has been explained with varying degrees of clarity and success by others.

What hasn't as yet been shown is how to work around the problem (in a large number of cases), though a couple came tantalisingly close to giving up that secret... :)

In your specific case you can get around the problem by reversing the "aliasing" of the value and the typed constant declaration as follows:

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

clLink now provides your true constant and clHotlight is the typed constant that has the same value as clLink.

For the GUID's the same technique can be used, but you have to bear in mind the normal constant expression used to initialise a typed GUID constant - it doesn't use a record but a simple literal string, so:

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

NOTE: Such GUID constants are perfectly usable in all places where TGUID's are required, e.g. IsEqualGUID( tguid, GUID_CONSTANT ) etc.

ˇ宁静的妩媚 2024-09-06 16:09:57

常量声明的右侧必须是“常量表达式”,其定义为“常量表达式是编译器可以在不执行其出现的程序的情况下计算的表达式”。您可以在语言指南中找到常量表达式的完整可接受语法。
请注意,语言指南明确指出“类型化常量不能出现在常量表达式中”。 - 这就是为什么你的声明失败,两个 clHotlight: TColor = $00FF9933;和管理员GUID:TGUID = ...;是类型常量。
此外,常量表达式不能包含除语言指南中列出的函数调用(即编译器能够在编译时计算的 Length()、SizeOf() 和其他一些函数)之外的函数调用。
这样重写:

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

它会起作用。

The right side of a constant declaration must be a "constant expression", which is defined as "a constant expression is an expression that the compiler can evaluate without executing the program in which it occurs". You can find the whole accepted syntax for constant expression in the language guide.
Note that the language guide explicitly states "Typed constants cannot occur in constant expressions." - and that's why your declarations fails, both clHotlight: TColor = $00FF9933; and AdministratorGUID: TGUID =...; are typed constants.
Also, constant expression cannot include functions calls except those listed in the language guide (i.e. Length(), SizeOf(), and some others) that the compiler is able to compute at compile time.
Rewrite this way:

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

And it will work.

千笙结 2024-09-06 16:09:57

欢迎来到德尔福进化。在delphi 1 & 2、不能将初始常量值赋给全局var(例如:var xVar:Integer = 1)。您可以做到这一点的唯一方法是使用 const xVar: Integer = 1) 以及代码中的某些位置,然后您可以根据需要将其更改为其他内容。在他们摆脱这个古老的功能之前,您不能使用“const xVar:Integer”构造作为const值。

干杯

welcome to Delphi evolution. in delphi 1 & 2, you can not assign initial constant value to a global var (ex: var xVar: Integer = 1). The only way you can do that is using const xVar: Integer = 1) and some where in you codes, you can then change it to somethingelse if desired. Until they get rid of this ancient feature, you can not using "const xVar: Integer" construct as a const value.

Cheers
A Pham

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文