跳至内容

Ada 编程/属性/'Base

来自维基教科书,开放的书籍,开放的世界

Ada. Time-tested, safe and secure.
Ada. 经久耐用、安全可靠。

表示另一个类型或子类型的基类型。此属性用于访问基类型的属性。

T'Base 指的是类型的“基范围”,它定义了中间计算执行的范围。

整数类型的基类型

[编辑 | 编辑源代码]

标准规定 T'Base 的范围

  1. 包括值 0
  2. 关于零对称,可能有一个额外的负值
  3. 包括子类型 T 中的所有值

例如,如果 T 是

 type T is range 1 .. 42;

那么编译器将选择一个包含此范围的硬件支持类型,在本例中可能是八位类型(在二进制补码机器上)

 type T'Base is range -128 .. 127;

此定义不应被理解为字面意思,因为根据 Ada 语义,T 和 T'Base 不兼容。实际上,T 的声明将是

 subtype T is T'Base range 1 .. 42;

请注意,内置运算符通过基类型执行,例如 T 的“+”运算符被隐式声明为

  function "+" (L, R : T'Base) return T'Base;

T'Base 上没有约束检查,例如

 declare
   O1 : T      := T'(1) + T'(2);
   O2 : T'Base := T'(1) + T'(2);
 begin

那么在对 O1 的第一次赋值中,有一个约束检查以确保 1 + 2 的结果在 T 的范围内,但在对 O2 的第二次赋值中,没有检查。

T'Base 对泛型很有用,当你需要能够恢复类型的基范围时,以便声明一个值为 0 的对象;例如,如果这是一个累加器。

了解类型的基范围是有帮助的,这样你就能保证在中间计算中不会发生溢出。例如,给定上面的类型 T,那么

 procedure Op (O1, O2 : T) is
   Sum : T'Base := O1 + O2;
 begin

这是一个问题,因为如果 O1 和 O2 的总和很大(即大于 T'Base'Last),那么就会发生溢出。知道要将两个值加在一起意味着你应该以这种方式声明类型

  T_Last : constant := 42;
  type T_Base is 0 .. 2 * T_Last;
  subtype T is T_Base range 1 .. T_Last;

这样你就知道(子)类型 T 的范围是 1 .. 42,但你也保证 T'Base'Last >= 84,因此两个类型 T 的值的总和不会溢出。

请注意,以下形式的声明

  type T is range ...

实际上声明了一个名为 T 的子类型,它属于某个匿名基类型。我们可以将此基类型的范围称为 T'Base。

枚举类型的基类型

[编辑 | 编辑源代码]

枚举类型是它自己的基类型,因此给定此类型

  type ET is (A, B, C);

那么 ET 的范围与 ET'Base 的范围相同。如果你在你的“基”类型中需要一些额外的文字,那么你必须手动声明它们,这与我们上面所做的类似

 type ET_Base is (ET_Base_First, A, B, C, ET_Base_Last);
 subtype ET is ET_Base range A .. C;

现在你可以说 ET'Succ (ET'Last),你将得到一个有意义的答案。这在执行以下操作时是必需的

 declare
   E : ET'Base := ET'First;
 begin
   while E <= ET'Last loop
     ... --  do something
     E := ET'Succ (E);
   end loop;
 end;

同样,当你从 ET_Base 派生并使用范围约束时,派生类型的基类型将包含基类型的所有值

 type New_ET is new ET_Base range A .. C;

 Correct: constant Boolean := New_ET'Base'First = ET_Base_First;

请注意,这里 ET_BASE_First 的类型为 New_ET。

如果你声明

type My_Enum is (Enum1, Enum2, Enum3);

并且

subtype Sub_Enum is My_Enum range Enum1 .. Enum2;

那么Sub_Enum'Base'LastEnum3.

维基教科书

[编辑 | 编辑源代码]

Ada 参考手册

[编辑 | 编辑源代码]
华夏公益教科书