Ada数据类型属性、类型限制和类型转换
数据类型属性,表示某个数据类型的具体特征---取值范围,最小值,最大值,某数在该类型中的位置 …… 应该说是相当有用的-----起码不像 C 语言,还要翻翻系统手册才能知道某个数据类型的具体定义。这些属性的用法和调用函数一样,也可以认为它们就是预定义的函数----虽然不怎么准确,有些返回值为通用类型(universal type)和字符串型。
数据类型的属性既可以使用预先定义的操作,也可以自己定义数据类型的属性,如S'First 是返回 S 类型的下限,如果用户不满意默认的属性,也可自己指定S'First(虽然没必要),如:
for S'First use My_Version_First;
My_Version_First 是用户自己的函数,以后当使用 S'First 时,实际上调用 My_Version_First;有些数据属性也可以直接用数字标示,如:
for S'First use 0;
这样,S'First 的值就成了0。在很多地方,如内存管理中,这种用法还是比较普遍的。下面简单地列出标量类型的属性,S 表示某个标量类型:
通用标量类型属性
S'First 返回 S 类型的下限,返回值为 S 型。
S'Last 返回 S 类型的上限,返回值为 S 型。
S'Range 返回 S 类型的取值范围,即 S'First .. S'Last。
S'Base 表示 S 类型的一个子类型,但没有范围限制(单纯从取值范围角度讲,“儿子”反而比“父母”大),称之为基类型(base type)。
S'Min 函数定义为: function (Left,Right:S'Base) return S'Base 。比较 Left和 Right 的大小,返回较小值。如:Integer'Min (1 , 2) = 1 。
S'Max 函数定义为: function (Left,Right:S'Base) return S'Base 。比较 Left和 Right 的大小,返回较大值。如:Integer'Max (1 , 2) =2 。
S'Succ 函数定义为:function S'Succ (Arg :S'Base) return S'Base 。返回 Arg 的后趋。
S'Pred 函数定义为: function S'Pred (Arg :S'Base) return S'Base 。返回 Arg的前趋。
S'Wide_Image 函数定义为:function S'Wide_Image (Arg : S'Base) return Wide_String 。返回 Arg 的“像”,即可显示的字符串,这里返回宽字符串型 Wide_String。如:Float'Wide_Image (9.00) = “9.00" 。详见 第三章 数组。
S'Image 与 S'Wide_Image 一样,但返回字符串型 String 。
S'Wide_Width 表示 S'Wide_Image 返回的字符串的最大长度,返回值为 universal_integer。
S'Width 表示 S'Image 返回的字符串的最大长度,返回值为 universal_integer。
S'Wide_Value 函数定义为: function S'Wide_Value ( Arg : Wide_String) return S'Base。是 S'Wide_Image 的逆过程,返回与“像”Arg 相对应的 S 类型的值。如: Float'Wide_Value ("9.00") = 9.00 。
S'Value 与 S'Value 一样,但参数 Arg 是 String 类型。
通用离散类型属性
离散类型包括整型和枚举型,除了上述的属性外,还有:
S'Pos 函数定义为: function S'Pos (Arg : S'Base) return universal_integer。返回 Arg 在 S 类型中的位置。
S'Val 函数定义为: function S'Pos (Arg : S'Base) return S'Base。返回 在 S 类型中位置为 Arg 的值。
例如:
type Color is (red, white, blue);
Color'Pos (White) = 2
Color'Val (1) = red
浮点类型属性
S'Digits 返回 S 类型的精度,为 universal_integer 类型。
定点类型属性
S'Small 返回 S 类型的 small 值,返回值为实型。
S'Delta 返回 S 类型的 delata,返回值为实型。
S'Fore 返回 S 类型所表示数的小数点前面的最小字符数量,返回值类型 universal_integer。
S'Alt 返回 S 类型所表示数的小数点后面的最小字符数量,返回值类型 universal_integer。
十进制定点型属性
S'Digits 返回 S 类型的精度。
S'Scale 返回 S 类型的标度 N,使 S'Delta=10.0**(-N)。
S'Round 函数定义为 function S'Round(X:universal_real) return S'Base;返回 X 的舍入值。
2.6 类型限制和类型转换(Type Qualification and Type Conversion)
先让我们看一下下面的例子:
type primary is (red, green, blue);
type rainbow is (red, yellow, green, blue, violet);
...
for i in red..blue loop
...
这里明显有歧义,编译器也就无法自动判定 red,blue 到底是 primary 还是 rainbow 中的元素。因此我们就需要使用类型限制,精确指明元素:
for i in rainbow'(red)..rainbow'(blue) loop
for i in rainbow'(red)..blue loop -- 只需要一个限制
for i in primary'(red)..blue loop
类型限制并不改变一个值的类型,只是告诉编译器程序员所期望的数据类型。由于 Ada 中提供了重载等特性,变量、子程序等重名的现象相当普遍,以后我们会碰到,解决方法和现在所讲的类型限制差不多,都是指明资源的准确位置。
类型转换我们也常常在使用,比方说 modular 类型的数的输入输出需要特定的程序包,初学者便可以将 modular 数转换成 Integer 数来处理(虽然不怎么好)。下面是一个 Integer 和 Float 类型数互相转换的例子:
X : Integer:= 4;
Y : Float;
Y := float(X);
. . .
X := Integer(Y);
这导致编译器插入合适的代码来做类型转换,实际效果就取决于编译器,而且一些类型之间的转换是禁止的;像上述的强行转换一般也不推荐,除非意义很明确,建议是使用上节所讲的数据类型属性、以及以后会碰到的相关子程序等来进行类型转换。
还有一种不进行检查的类型转换,我们会在以后遇到。
类型限制和类型转换
先让我们看一下下面的例子:
type primary is (red, green, blue);
type rainbow is (red, yellow, green, blue, violet);
...
for i in red..blue loop
...
这里明显有歧义,编译器也就无法自动判定 red,blue 到底是 primary 还是 rainbow 中的元素。因此我们就需要使用类型限制,精确指明元素:
for i in rainbow'(red)..rainbow'(blue) loop
for i in rainbow'(red)..blue loop -- 只需要一个限制
for i in primary'(red)..blue loop
类型限制并不改变一个值的类型,只是告诉编译器程序员所期望的数据类型。由于 Ada 中提供了重载等特性,变量、子程序等重名的现象相当普遍,以后我们会碰到,解决方法和现在所讲的类型限制差不多,都是指明资源的准确位置。
类型转换我们也常常在使用,比方说 modular 类型的数的输入输出需要特定的程序包,初学者便可以将 modular 数转换成 Integer 数来处理(虽然不怎么好)。下面是一个 Integer 和 Float 类型数互相转换的例子:
X : Integer:= 4;
Y : Float;
Y := float(X);
. . .
X := Integer(Y);
这导致编译器插入合适的代码来做类型转换,实际效果就取决于编译器,而且一些类型之间的转换是禁止的;像上述的强行转换一般也不推荐,除非意义很明确,建议是使用上节所讲的数据类型属性、以及以后会碰到的相关子程序等来进行类型转换。
还有一种不进行检查的类型转换,我们会在以后遇到。