Delphi 积分真常数的类型是什么?

Delphi 积分真常数的类型是什么?,delphi,Delphi,我很抱歉问了一个非常基本的问题。考虑下面的例子: const c1 = 1; // Is this Byte or ShortInt? c2 = 1234; // Is this Word or Smallint? c3 = 123456; // Is this Cardinal or Integer? 读完这篇文章后,我可以得出结论,负值被解释为有符号,而正值被解释为无符号。但是,例如,123456(根据文档将其解释为Cardinal)也可以在Integer的上下文

我很抱歉问了一个非常基本的问题。考虑下面的例子:

const
  c1 = 1;      // Is this Byte or ShortInt?
  c2 = 1234;   // Is this Word or Smallint?
  c3 = 123456; // Is this Cardinal or Integer?

读完这篇文章后,我可以得出结论,负值被解释为有符号,而正值被解释为无符号。但是,例如,123456(根据文档将其解释为
Cardinal
)也可以在
Integer
的上下文中使用,我的意思是在计算中使用常量的
Integer
变量中使用。因此,常量是否保证始终是
基数
,因此必须将其转换为
整数

回答您的原始问题:

每个常量的数据类型是什么

它们或多或少是非类型化的,并且在使用它们时假定一种类型,如文字值。它们不占用空间,通常没有地址,除非它们必须(例如字符串、集合等)。你可以认为它们是“代表文字的符号”。它们可以与C中的简单定义(IOW,文本替换)或汇编程序中的立即值相比较。所以
'C'
可以是
AnsiChar
WideChar
AnsiString
WideString
UnicodeString
,甚至可以分配给
PChar
PWideChar
panichar
。类型取决于分配给它的内容,就像,一个文本。整数值或浮点类型、集合类型等也一样

请注意,如果您要求,编译器(以及-IMO不正确-文档)将为您提供一个类型,通常是可以容纳它的最小整数类型,或者是浮点值的
扩展
双精度
,或者它所属的枚举或集合类型。但那是,除非你问

常量表达式中只能使用“非类型化”或true常量。类型化常量(占用实空间的IOW常量)就像你说的,或多或少像“不可变变量”(是的,我知道这是一个矛盾修饰法),IOW,它们有一个地址,一个类型,一个定义的大小,但它们不是,呃,变量或可变的(就像David说的,忘记可写的类型化常量)

我相信这里的一些人会完全不同意,但是,嘿,这就是我一直认为的真实常数,这种观点从未让我失望过

如何强制常量具有特定的数据类型?我的意思是除了类型化常量之外的另一种方式,如果我是对的,它实际上是常量变量

通过强制转换,可以为类型指定一个真常量:

const
  Bla = UInt64(1234); // $0000000000001234
  Doo = Cardinal(-1); // $FFFFFFFF
  Duh = Shortint(rfReplaceAll);
不过,我认为您不能强制转换为一种浮点类型。此类强制转换通常是禁止的,对于常量也是如此(AFAIK,现在无法测试)

现在期待一些尖锐的评论或否决票。:-)

更新 因此,是否保证常量始终为基数,以便有必要将类型转换为整数

不需要石膏。无论如何,该类型并不总是
Cardinal
,即使文档这么说(正如我所说,我认为他们错了)。Is只是就好像您在该位置使用了文本值
123456
。你可以说,
123456
也有一个类型,但实际上,假装它没有要容易得多。类型取决于上下文,它可能被编译为

        MOV     EAX,123456
        MOV     [TheVariable],EAX
如何解释取决于变量的类型。例如,如果您这样做:

MyDouble := 123456;
这并不意味着编译了
基数
,必须进行到
双精度
的转换。它直接编译为
Double
123456.0
。可能存在转换,但仅在编译器内部

因此,我想,不要再担心这些常量的类型了。Simple将它们视为表示文字的符号,并假设它们将获得您期望的类型。你很少会错。

证明 请看下面的代码:

const
  CHi = 'Hello';
  CInt = $1234;
  CTInt: Word = $1234;

var
  CVInt: Word = $1234;

procedure Test;
var
  A: AnsiString;
  U: UnicodeString;
  I: Integer;
  D, E, F: Double;
begin
  A := CHi;
  U := CHi;
  I := CInt;
  D := CInt;
  E := CTInt;
  F := CVInt;
  Writeln(A, U, I, D); // Just to make this compile.
end;
而这个的拆卸,

Project44.dpr.25: A := CHi;
00419584 8D45FC           lea eax,[ebp-$04]
00419587 BA40964100       mov edx,$00419640
0041958C E84BE0FEFF       call @LStrLAsg
Project44.dpr.26: U := CHi;
00419591 8D45F8           lea eax,[ebp-$08]
00419594 BA54964100       mov edx,$00419654
00419599 E8A2DFFEFF       call @UStrLAsg
Project44.dpr.27: I := CInt;
0041959E C745F434120000   mov [ebp-$0c],$00001234
Project44.dpr.28: D := CInt;
004195A5 33C0             xor eax,eax
004195A7 8945E8           mov [ebp-$18],eax
004195AA C745EC0034B240   mov [ebp-$14],$40b23400
Project44.dpr.29: E := CTInt;
004195B1 0FB705A0D54100   movzx eax,[$0041d5a0]
004195B8 8945D4           mov [ebp-$2c],eax
004195BB DB45D4           fild dword ptr [ebp-$2c]
004195BE DD5DE0           fstp qword ptr [ebp-$20]
004195C1 9B               wait
Project44.dpr.30: F := CVInt;
004195C2 0FB705A2D54100   movzx eax,[$0041d5a2]
004195C9 8945D4           mov [ebp-$2c],eax
004195CC DB45D4           fild dword ptr [ebp-$2c]
004195CF DD5DD8           fstp qword ptr [ebp-$28]
004195D2 9B               wait
如您所见,字符串常量的值在分配给
AnsiString
UnicodeString
时不相同。复制反汇编的数据部分并不容易,因此您必须在自己的Delphi IDE中进行检查,但在地址
$0041961C
处,有一个文本解析(refcount-1)'Hello',而在地址
$00419630
处,有一个文本解构'Hello'。这意味着常量被编译为上下文所需的类型,不再需要显式或隐式转换(即从
UnicodeString
AnsiString
,或从
Word
Double

还要注意的是,与true常量相反,类型化的常量确实需要转换代码。字作为
movzx eax,[$0041d5a0]
加载,即从
word
转换为
DWord
,然后存储为
DWord
,作为
DWord
加载到FPU,然后存储为64位浮点值(
Double
)。这是一个你看不到的转换,因为它对于真常数来说是不需要的

我知道有些人会说:“嗯,这是一辆破车,但编译器先将其转换为AnsiString。”在我看来,这就像是说:“汽车的原始车身是灰色的,但在出售(分配)之前,它必须被漆成绿色。”我宁愿说:“出售的汽车是绿色的,不管它是如何得到那种颜色的。”当然,文本和常量(IOW,在
常量
部分中定义的符号)将具有默认类型,在查询时给出,并且不请求特定类型,但是出于所有实际目的,如果简单地将它们视为“带名称标签的文本”,而将视为特定类型,则最简单,低a
if @CInt = nil then;
if @CTInt = nil then;
program SO32160057_overloads;

{$APPTYPE CONSOLE}

procedure foo(value: UInt8); overload;
begin
  Writeln('UInt8');
end;

procedure foo(value: UInt16); overload;
begin
  Writeln('UInt16');
end;

procedure foo(value: UInt32); overload;
begin
  Writeln('UInt32');
end;

procedure foo(value: UInt64); overload;
begin
  Writeln('UInt64');
end;

procedure foo(value: Int8); overload;
begin
  Writeln('Int8');
end;

procedure foo(value: Int16); overload;
begin
  Writeln('Int16');
end;

procedure foo(value: Int32); overload;
begin
  Writeln('Int32');
end;

procedure foo(value: Int64); overload;
begin
  Writeln('Int64');
end;

const
  ZeroInt32 = Int32(0);
  ZeroUInt16 = UInt16(0);

begin
  foo(127);
  foo(128);

  foo(32767);
  foo(32768);

  foo(2147483647);
  foo(2147483648);

  foo(9223372036854775807);
  foo(9223372036854775808);

  foo(ZeroInt32);
  foo(ZeroUInt16);
  foo(UInt8(0));
end.
Int8 UInt8 Int16 UInt16 Int32 UInt32 Int64 UInt64 Int32 UInt16 UInt8
program SO32160057_comparisons;

var
  Int8var:  Int8  = 0;
  Int16var: Int16 = 0;
  Int32var: Int32 = 0;

begin
  if Int8var  <              127  then ;
  if Int8var  <              128  then ;  // line 10
  if Int8var  <        Int16(128) then ;  // line 11
  if Int16var <            32767  then ;
  if Int16var <            32768  then ;  // line 13
  if Int16var <      Int32(32768) then ;  // line 14
  if Int32var <       2147483647  then ;
  if Int32var <       2147483648  then ;  // line 16
  if Int32var < Int64(2147483648) then ;
end.
(10): W1022 Comparison always evaluates to True (10): W1023 Comparing signed and unsigned types - widened both operands (11): W1022 Comparison always evaluates to True (13): W1022 Comparison always evaluates to True (13): W1023 Comparing signed and unsigned types - widened both operands (14): W1022 Comparison always evaluates to True (16): W1022 Comparison always evaluates to True (16): W1023 Comparing signed and unsigned types - widened both operands
program SO32160057_123456;

var
  UInt32var: UInt32 = 0;

begin
  if UInt32var >  123456 then ; // line 7
  if UInt32var > -123456 then ; // line 8
end.
(8): W1022 Comparison always evaluates to True (8): W1023 Comparing signed and unsigned types - widened both operands