Types 为什么Ada编译器允许范围冲突通过?为什么我的类型声明是运行时实体?

Types 为什么Ada编译器允许范围冲突通过?为什么我的类型声明是运行时实体?,types,runtime,range,ada,compile-time,Types,Runtime,Range,Ada,Compile Time,为什么Ada编译器允许范围冲突通过? 它确实发出警告,但如果它在任何情况下都是错误,为什么它会让它通过呢?是否存在这样一种实际情况,即这是一种有用的行为 最重要的是:为什么类型声明是运行时实体? 我的意思是代码示例的第三行是我希望提前评估的内容。 我认为只有第5行会“makeit”进入可执行文件。为什么不呢?这有用吗?我是否在这里遗漏或误解了什么 with Ada.Text_IO; procedure question is subtype Test is Natural range -

为什么Ada编译器允许范围冲突通过? 它确实发出警告,但如果它在任何情况下都是错误,为什么它会让它通过呢?是否存在这样一种实际情况,即这是一种有用的行为

最重要的是:为什么类型声明是运行时实体? 我的意思是代码示例的第三行是我希望提前评估的内容。 我认为只有第5行会“makeit”进入可执行文件。为什么不呢?这有用吗?我是否在这里遗漏或误解了什么

with Ada.Text_IO;
procedure question is
    subtype Test is Natural range -1 .. 10;
begin
    Ada.Text_IO.Put_Line ("foobar");
end;
注:结果与“型式试验为新的自然范围-1..10

注意:GNAT 4.6建议您至少需要
-gnato-fstack check
命令行选项才能使GNAT成为兼容的Ada编译器

然而,这不是问题所在:编译器确实会警告范围错误;有了蚊虫,我得到了:

gnatmake -gnato -fstack-check question
question.adb:3:35: warning: static value out of range of type "Standard.Natural"
question.adb:3:35: warning: "Constraint_Error" will be raised at run time
以及运行时的明显错误

在这种情况下,由于范围是静态的,编译器可能捕获到错误;但是,正如您所猜测的,通常在运行时之前无法完全确定类型,如下面的示例所示

with Ada.Text_IO;
with Ada.Command_Line;

procedure question is
   subtype Arguments is Natural range 1 .. Ada.Command_Line.Argument_Count;
begin
   for i in Arguments loop
      Ada.Text_IO.Put_Line ("Argument " & integer'image(i) & 
                            " is " & Ada.Command_Line.Argument(i)); 
      declare
         OneArg : constant String := Ada.Command_Line.Argument(i);
         subtype Characters is Natural range OneArg'range;
      begin
         null;  -- process the string here
      end;   
   end loop;
end;
在这里,在运行程序之前,两个子类型都是未知的


declare块显示了一个我认为非常有用的相关模式,它不仅允许变量[sub]类型,而且在堆栈上分配可变大小的对象,以便在每次循环迭代中自动回收和重新调整它们的大小。(与其他语言一样,您可以使用“new”进行分配,使用“unchecked_deallocation”进行免费分配,但通常情况下,就像这里一样,根本不需要)

值得一提的是哪种Ada编译器和版本。顺便问一下,您知道Gnat在默认情况下不是Ada编译器吗?它需要一组特定的编译器标志来打开标准要求的某些检查!