为什么Ada没有捕获这个指定的范围检查?

11

我正在学习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;
4个回答

11

你已经看到了几个不错的答案,但是我想再添加一个,因为很明显你期望表达式 D + 1.0 抛出异常,而现有的答案没有解释为什么不会抛出异常。

像这样的类型声明:

type T_Norm is new float range -1.0 .. 1.0;

大致相当于

type T_Norm'Base is new Float;
subtype T_Norm is T_Norm'Base range -1.0 .. 1.0;

这个类型(称为“基本类型”)没有被命名,尽管通常可以用'Base属性引用它。给出的名称是一个子类型的名称,称为“第一命名子类型”。

这个区别很重要,常常没有得到足够的关注。如egilhh所解释的那样,T_Norm'Image是基于T_Norm'Base定义的。算术运算符也是如此。例如,"+"被定义为

function "+" (Left : in T_Norm'Base; Right : in T_Norm'Base) return T_Norm'Base;

2.0显然在T_Norm'Base范围内,因此评估D + 1.0不违反任何限制,也不会将其传递到T_Norm'Image。但是,当您尝试将结果值分配给具有子类型T_NormD时,会执行检查以确保该值处于子类型的范围内,并且因为检查失败而引发异常。

这种区别在其他地方用于使语言合理地工作。例如,约束数组类型。

type A is array (1 .. 10) of C;

大致等同于

type A'Base is array (Integer range <>) of C;
subtype A is A'Base (1 .. 10);

如果你这样做

V : A;
... V (2 .. 4)

你可能会因为切片没有A的边界而期望出现问题。但它能正常工作的原因是该切片不具有子类型A,而是匿名子类型A'Base (2..4)


非常感谢您。我还没有达到Ada知识的那个水平,但这提供了更清晰的理解。 - hypotenuse

7

'Image的定义如下:

对于任何标量子类型S:

S'Image表示具有以下规范的函数:

function S'Image(Arg : S'Base) return String

可以看到,它接受一个基础(无限制)类型的参数。


谢谢。我会查看定义。 - hypotenuse

3

T_Norm'Image(D + 1.0)既不赋值也不读取超出范围的值。它请求(D + 1.0)的'Image属性(字符串表示),这与请求(1.0 + 1.0)相同。

我认为混淆可能有两种方式。首先,名称“attribute”可能被误解为暗示了'Image涉及到D内在的某些东西。它并没有。'Image属性只是一个函数,因此D只是定义参数值的表达式的一部分(在您的例子中=2.0)。

第二,'Image属性来自Float。 因此,任何Float都可以成为它的参数。

您可以创建一个仅接受T_Norm'Range参数的函数,并将该函数作为T_Norm的属性。请参见Ada参考手册4.10。


RM 4.10目前尚不存在。它只是即将推出的语言修订草案Ada 202x的一部分。 - egilhh
我的假设是它在某种程度上是D的属性,因此感到困惑。感谢所有帮助过我的人。我将来会检查定义。 - hypotenuse

2

因为在 D 中没有存储大于范围的值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接