我正在阅读 learn.adacore.com 教程,但遇到了一个我不确定的问题。
具体来说,我知道 Ada 旨在捕获试图溢出具有指定范围定义的变量的尝试。
在下面的情况下,第一次尝试这样做会导致编译器“范围检查失败”,这是预期的。但是以下行并没有捕获它,我不知道为什么:
with Ada.Text_IO; use Ada.Text_IO;
procedure Custom_Floating_Types is
type T_Norm is new float range -1.0 .. 1.0;
D : T_Norm := 1.0;
begin
Put_Line("The value of D =" & T_Norm'Image(D));
-- D := D + 1.0; -- This causes a range check failure at run time = completely expected.
Put_Line("The value of D =" & T_Norm'Image(D + 1.0)); -- This doesn't?
end Custom_Floating_Types;
Run Code Online (Sandbox Code Playgroud)
Jef*_*ter 11
您有几个很好的答案,但我将添加另一个,因为很明显您希望表达式D + 1.0引发异常,而您的答案没有解释为什么不会。
像这样的类型声明
type T_Norm is new float range -1.0 .. 1.0;
Run Code Online (Sandbox Code Playgroud)
大致相当于
type T_Norm'Base is new Float;
subtype T_Norm is T_Norm'Base range -1.0 .. 1.0;
Run Code Online (Sandbox Code Playgroud)
类型(称为“基本类型”)没有命名,尽管它通常可以用'Base属性引用。给出的名称是一个子类型,称为“第一个命名的子类型”。
这种区别很重要,但往往没有得到足够的重视。正如 egilhh 所解释的那样,T_Norm'Image是根据 定义的T_Norm'Base。算术运算符也是如此。例如,"+"定义为
function "+" (Left : in T_Norm'Base; Right : in T_Norm'Base) return T_Norm'Base;
Run Code Online (Sandbox Code Playgroud)
2.0 显然在 的范围内T_Norm'Base,因此评估D + 1.0不会违反任何约束,也不会将其传递给T_Norm'Image。但是,当您尝试将结果值分配给D具有 subtype 的 时T_Norm,将执行检查该值是否在子类型的范围内,并且由于检查失败而引发异常。
这种区别在其他地方使用,使语言可以合理地工作。例如,一个受约束的数组类型
type A is array (1 .. 10) of C;
Run Code Online (Sandbox Code Playgroud)
大致相当于
type A'Base is array (Integer range <>) of C;
subtype A is A'Base (1 .. 10);
Run Code Online (Sandbox Code Playgroud)
如果你这样做
V : A;
... V (2 .. 4)
Run Code Online (Sandbox Code Playgroud)
您可能会遇到问题,因为切片没有A. 但它有效,因为切片没有子类型A,而是匿名子类型A'Base (2 ..4)。
'图像的定义说:
对于每个标量子类型 S:
S'Image 表示具有以下规范的函数:
函数 S'Image(Arg : S'Base) 返回字符串
如您所见,它接受一个基本(无约束)类型的参数