整数真常数的类型是什么? [英] What is the type of a integral true constant?

查看:89
本文介绍了整数真常数的类型是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很抱歉提出一个非常基本的问题。考虑下面的示例:

I'm sorry for asking a very basic question. Consider the following example:

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

阅读此文档,我可以得出的结论是,负值解释为 signed ,正值解释为 unsigned 。但是,例如 123456 (根据文档将其解释为 Cardinal )也可以在 Integer 上下文中使用。 code>,我的意思是它在 Integer 变量中使用,该变量在计算中使用常量。因此,常量保证始终是基数,以便有必要对 Integer 进行类型转换。 ?

After reading this documentation, what I can conclude is that negative value is interpreted as signed, and positive value is interpreted as unsigned. However, e.g. 123456 (which according to the documentation will be interpreted as Cardinal) can also be used in a context of Integer, I mean it is used in an Integer variable that uses the constant in calculation. Therefore, is the constant guaranteed to be always Cardinal so that a typecast to Integer necessary?

推荐答案

文档(XE8是我撰写本文时的最新版本),它告诉您 true常量具有类型。但是,在指定该类型实际是什么时,该文档具有误导性。当我说误导时,我有点友善。

The documentation (XE8 is the latest version as I write this) tells you that true constants have a type. However, the documentation is misleading when it comes to specifying what that type actually is. And when I say misleading, I am being somewhat kind.

您是在阅读本官方文档,那么您倾向于认为无符号类型比有符号类型更受青睐。但是此程序表明情况并非如此:

Were you to read this official documentation then you would be inclined to believe that unsigned types are preferred to signed types. But this program shows that is not the case:

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

让我们看看另一个程序:

Let's have a look at another program:

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






因此,根据我的经验分析,编译器查看整数文字的值,并通过在以下列表中找到可以表示该值的第一个类型来确定其类型:


So, by my empirical analysis, the compiler looks at the value of an integral literal, and determines its type by finding the first type in the following list which can represent the value:


  • Int8

  • UInt8

  • Int16

  • UInt16

  • Int32

  • UInt32

  • Int64

  • UInt64

  • Int8
  • UInt8
  • Int16
  • UInt16
  • Int32
  • UInt32
  • Int64
  • UInt64

可以通过使用typecast语法指定类型来覆盖此规则。例如,要声明值 0 Int32 ,您应编写 Int32(0)

This rule can be overridden by specifying the type using the typecast syntax. For instance, to declare an Int32 with value 0 you would write Int32(0).

现在,让我们将该规则应用于您在问题中给出的具体示例,即 123456 。根据上述规则,列表中可以表示该值的第一种类型是 Int32 。现在也称为 Integer

Now let us apply that rule to the concrete example that you give in the question, namely 123456. According to the rules above, the first type in the list which can represent this value is Int32. Also known as Integer.

现在,由于这是一个无符号类型,您可能希望将其与未签名的 UInt32 变量将导致警告W1023,比较有符号和无符号类型。但事实并非如此。编译器认识到 123456 是一个正值,并且我们正在比较两个正值。另一方面,警告与 -123456 一起发出。

Now, because this is an unsigned type, you might expect that a comparison against an unsigned UInt32 variable will result in warning W1023, comparing signed and unsigned types. But that is not the case. The compiler recognises that 123456 is a positive value and that we are comparing two positive values. On the other hand, the warning is emitted with -123456.

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

这篇关于整数真常数的类型是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆