在我正在阅读的一本教科书中声明“虽然在编译时检查类型是否兼容,但子范围需要运行时范围检查。” 如果我得到正确的结果,则必须在将新值分配给在特定子范围(子类型)中定义的变量时执行运行时检查。类型不一样吗?为什么这个区别?这只是编译器的默认值?类型检查和范围检查
回答
的确如此,从类型U
的子类型P
分配将不需要检查,因为不会有失配(即使子类型与该类型具有相同的范围; subtype P is U;
是完全合法的,并且可以是有用!)
另一种方式,从类型到子类型,将涉及检查,至少如果子类型是子范围。
从外部看,另一种不同范围的类型也是如此。但是,有一个微妙的差异,使用类型/子类型,您可以在不进行转换的情况下将一个转换为另一个,如果不是没有转换,但是对于类型/类型,您必须在转换之前进行类型转换,并且将在转换时检查违反约束的条件,而不是转让。
这可能有助于说明这一点:
procedure Drimades is
type Upper is range 10 .. 20;
subtype Part is Upper range 10 .. 15;
type Lower is new Upper range 10 .. 15;
procedure Assign_U_To_P (U : Upper; To : out Part) is
begin
To := U; -- requires check
end Assign_U_To_P;
procedure Assign_P_To_U (P : Part; To : out Upper) is
begin
To := P; -- no check needed
end Assign_P_To_U;
procedure Assign_U_To_L (U : Upper; To : out Lower) is
begin
To := Lower (U); -- requires check
end Assign_U_To_L;
procedure Assign_L_To_U (L : Lower; To : out Upper) is
begin
To := Upper (L); -- no check required
end Assign_L_To_U;
U : Upper;
P : Part;
L : Lower;
begin
Assign_U_To_P (20, P);
Assign_P_To_U (15, U);
Assign_U_To_L (20, L);
Assign_L_To_U (15, U);
end Drimades;
与GNAT和-gnatG
产生这种中间表示,不要太用力,解释我希望开关编译如下:
procedure drimades is
type drimades__upper is range 10 .. 20;
[type drimades__TupperB is new short_short_integer]
freeze drimades__TupperB []
subtype drimades__part is drimades__upper range 10 .. 15;
[type drimades__TlowerB is new drimades__TupperB]
freeze drimades__TlowerB []
type drimades__lower is new drimades__upper range 10 .. 15;
procedure drimades__assign_u_to_p (u : drimades__upper; to : out
drimades__part) is
begin
[constraint_error when
not (u in 10 .. 15)
"range check failed"]
to := u;
return;
end drimades__assign_u_to_p;
procedure drimades__assign_p_to_u (p : drimades__part; to : out
drimades__upper) is
begin
to := p;
return;
end drimades__assign_p_to_u;
procedure drimades__assign_u_to_l (u : drimades__upper; to : out
drimades__lower) is
begin
[constraint_error when
not (u in 10 .. 15)
"range check failed"]
to := drimades__lower(u);
return;
end drimades__assign_u_to_l;
procedure drimades__assign_l_to_u (l : drimades__lower; to : out
drimades__upper) is
begin
to := drimades__upper(l);
return;
end drimades__assign_l_to_u;
u : drimades__upper;
p : drimades__part;
l : drimades__lower;
begin
drimades__assign_u_to_p (20, p);
drimades__assign_p_to_u (15, u);
drimades__assign_u_to_l (20, l);
drimades__assign_l_to_u (15, u);
return;
end drimades;
Simon Wright's answer地址从Ada及其亚型的角度提问,这意味着子集中的某个值,因此不是Ada或C++所称的派生的类型或派生的类别,分别。 (型Lower
是新Upper
... ;
使得Lower
是衍生从Upper
,则所创建的子类型的“...”限定进一步的特征。)
更一般地,一些语言允许任何变量名在运行时引用任何类型的对象。因此,在JavaScript中,
var a = 15, b = -1;
...
a = {"foo": "bar"}
...
return a + b;
将返回可能令人惊讶的结果,但如果通过语言判断则结果很好。 a
在第二行上被赋予不同类型的新值,并且+
将在第三行上产生来自a
和b
的东西。
在Ada,C或Swift等语言中,并不需要这种灵活性:用这种语言编写的程序可以在任何计算机设备上运行,这意味着不会像字典一样在一个位置对象声明是一些整数类型,说。编译时间类型检查可以防止这种情况。在分配(或传递)对象时需要在编译时检测到任何“不尊重”。
除编译时类型检查外,Ada还使用基于名称的类型等价。所以,
type Apples is range 0 .. 20;
type Oranges is range 0 .. 20;
a : Apples := 5;
b : Oranges := 8;
return a + b; -- Error!
你得到
8. return a + b; -- Error!
|
>>> invalid operand types for operator "+"
>>> left operand has type "Apples" defined at line 2
>>> right operand has type "Oranges" defined at line 3
这是纯粹的类型,在编译时检查。最后,扩展Simon Wright的例子说明的内容,有时Ada甚至要求在编译时检查子类型。然后涉及的短语是静态匹配,其中静态意味着编译时。例如,相同的边界。但是,这是先进的东西发生,例如,当指针指向堆栈上的对象,并且这些指针具有与指针不同的范围(子类型)时。
- 1. SQL查询检查范围
- 2. 会员检查和日期范围检查在Matlab
- 3. 检查范围重叠
- 4. MySQL:BETWEEN ..如何检查范围?
- 5. ArrayList范围检查错误
- 6. PHP - 检查日期范围
- 7. 复制的范围和重复检查
- 8. 表格插入和范围检查?
- 9. 检查类型
- 10. 类(类型)检查
- 11. 使用枚举进行类型检查 - 如何正确范围
- 12. XSLT类型检查
- 13. typedef类型检查?
- 14. 类型检查Erlang
- 15. Prolog类型检查
- 16. 检查Genric类型
- 17. Typetree类型检查
- 18. C#泛型和类型检查
- 19. Django模型继承和类型检查
- 20. 检查泛型类型是
- 21. 类型检查的子类
- 22. Elif声明检查表单范围
- 23. 检查范围是不是整个表?
- 24. 检查ipAddress是否在私人范围
- 25. 的Javascript检查是否范围重叠
- 26. c中的范围检查是什么?
- 27. 如何检查数组的范围?
- 28. 添加范围检查的EditText
- 29. 检查信息的范围 - 双击
- 30. 范围检查错误画布
你在说什么语言? –
它适用于Ada,也可能适用于其他语言。 –
当你说“subrange check”时,你的意思是检查在收集元素(如数组)时特定索引是否在允许范围内?或者它有什么不同? – oldbam