Originale-mail to me for new edition

 

Subrange types

 

A subrange type represents a subset of the values in another ordinal type (called the base type). Any construction of the form Low..High, where Low and High are constant expressions of the same ordinal type and Low is less than High, identifies a subrange type that includes all values between Low and High. For example, if you declare the enumerated type

type TColors = (Red, Blue, Green, Yellow, Orange, Purple, White, Black);

you can then define a subrange type like

type TMyColors = Green..White;

Here TMyColors includes the values Green, Yellow, Orange, Purple, and White.

You can use numeric constants and characters (string constants of length 1) to define subrange types:

type

  SomeNumbers = -128..127;

  Caps = 'A'..'Z';

When you use numeric or character constants to define a subrange, the base type is the smallest integer or character type that contains the specified range.

The Low..High construction itself functions as a type name, so you can use it directly in variable declarations. For example,

var SomeNum: 1..500;

declares an integer variable whose value can be anywhere in the range from 1 to 500.

The ordinality of each value in a subrange is preserved from the base type. (In the first example above, if Color is a variable that holds the value Green, Ord(Color) returns 2 regardless of whether Color is of type TColors or TMyColors.) Values do not wrap around the beginning or end of a subrange, even if the base is an integer or character type; incrementing or decrementing past the boundary of a subrange simply converts the value to the base type. Hence, while

type Percentile = 0..99;

var I: Percentile;

...

I := 100;

produces an error,

...

I := 99;

Inc(I);

assigns the value 100 to I (unless compiler range-checking is enabled).

The use of constant expressions in subrange definitions introduces a syntactic difficulty. In any type declaration, when the first meaningful character after = is a left parenthesis, the compiler assumes that an enumerated type is being defined. Hence the code

const

  X = 50;

  Y = 10;

type

  Scale = (X - Y) * 2..(X + Y) * 2;

produces an error. Work around this problem by rewriting the type declaration to avoid the leading parenthesis:

type

  Scale = 2 * (X - Y)..(X + Y) * 2;

 

Topic groups

 

See also

Character strings

Integer types

Numerals

Ordinal types: Overview

 

 

译文

 

子界类型

 

一个子界类型表示相应序数类型(在此叫做基类型base type)中值的子集。任何形如Low..High(这里,LowHigh是相同序数类型的常量表达式并且Low小于High)的结构,都表示一个子界类型,该子界包括LowHigh之间所有的值。例如,对于已声明的枚举类型

type TColors = (Red, Blue, Green, Yellow, Orange, Purple, White, Black);

可以定义如下子界类型

type TMyColors = Green..White;

这里,TMyColors包括GreenYellowOrangePurpleWhite等值。

 

还可以用数字和字符(长度是1的串)定义子界类型:

type

  SomeNumbers = -128..127;

  Caps = 'A'..'Z';

 

用数字或字符常量定义子界时,基类型是包含指定范围的最小整数类型或字符类型。Low..High结构本身也可以作为类型名称,因此可以直接用于变量声明。例如:

var SomeNum: 1..500;

声明了一个整数变量,其值的范围是1500

 

子界类型中每个值的序号与其基类型保持一致。(在上面第一个例子中,如果Color是一个值为Green的变量,那么表达式 Ord(Color) 总返回2,而不管变量Color的类型是TColors还是TMyColors。)子界类型的值不会在子界的起点和终点循环,即使基类型是整数或字符类型;对子界类型的边界值递增或递减,只是对其基类型转换相应的值。因此,下面的语句

type Percentile = 0..99;

var I: Percentile;

...

I := 100;

将导致编译错误,而语句

...

I := 99;

Inc(I);

将把值100赋给变量 I (除非范围检查编译指示有效,即{$R+})。由此也可以看出,子界类型与其基类型的范围一致时,其临界值(最小值和最大值)之间是循环的。

 

定义子界类型时,常量表达式的使用引出一个造句难点。对于任何类型声明,出现在等号(=)右边第一个有意义的字符如果是圆括号,那么编译器总是假定枚举类型将被定义。因此,

const

  X = 50;

  Y = 10;

type

  Scale = (X - Y) * 2..(X + Y) * 2;

将导致编译错误。要避免此类问题,可以写成如下声明形式(编者注,相信在将来的Object Pascal版本中,这一问题会得到解决或改善):

type

  Scale = 2 * (X - Y)..(X + Y) * 2;

 

主题组

 

相关主题

字符串

整数类型

数字

序数类型:概述