単純型(Delphi)
目次 |
単純型には順序型と実数型があり、順序付けされた値の集合を定義します。
順序型
順序型には、整数型、文字型、論理型、列挙型、および部分範囲型が含まれます。順序型は、順序付けされた値の集合を定義します。この集合では、値(最初の値を除きすべて)の前の値と、値(最後の値を除きすべて)の後の値が、それぞれ一意に決まっています。さらに、すべての値が順序値を持ち、これによって型の順序付けが決定されます。ほとんどの場合、値の順序値が n であれば、前の値の順序値は n - 1 であり、後の値の順序値は n + 1 です。
整数型の場合、順序値は値そのものです。部分範囲型はその基底型の順序値を保持します。その他の順序型では、デフォルトで最初の値の順序値が 0、次の値の順序値が 1 というように決まっています。列挙型を宣言すると、このデフォルト値を明示的にオーバーライドできます。
順序型の値と型識別子を処理する複数の定義済み関数があります。特に重要なものを以下に示します。
| 関数 | パラメータ | 戻り値 | 説明 |
|---|---|---|---|
|
Ord |
順序型の式 |
式の値の順序値 |
Int64 の引数をとらない |
|
Pred |
順序型の式 |
式の値の前の値 |
|
|
Succ |
順序型の式 |
式の値の次の値 |
|
|
High |
順序型の型識別子または順序型の変数 |
型の最大の値 |
短い文字列型と配列型も処理できる |
|
Low |
順序型の型識別子または順序型の変数 |
型の最小の値 |
短い文字列型と配列型も処理できる |
たとえば、Byte 型の最大の値は 255 なので、High(Byte) は 255 を返します。2 の次の値は 3 なので、Succ(2) は 3 を返します。
標準手続き Inc と Dec は順序型変数の値をインクリメントおよびデクリメントします。たとえば、Inc(I) は I := Succ(I) と同じであり、I が整数変数である場合は I := I + 1 と同じです。
整数型
整数型は汎整数の部分集合を表します。
整数型には、プラットフォーム依存のものとプラットフォーム非依存のものがあります。
プラットフォーム依存の整数型
プラットフォーム依存の整数型は、現在のコンパイラ プラットフォームのビットサイズに合わせて変換されます。プラットフォーム依存の整数型は NativeInt と NativeUInt です。結果的に、ベースとなる CPU およびオペレーティング システムの最高のパフォーマンスが得られるため、できるだけこれらの型を使用します。以下の表では、これらの型の値の範囲と格納形式を Delphi コンパイラの場合について示します。
プラットフォーム依存の整数型
| 型 | 値の範囲 | 形式 | エイリアス |
|---|---|---|---|
|
|
符号付き 32 ビット(32 ビット プラットフォーム上)または |
||
|
|
符号なし 32 ビット(32 ビット プラットフォーム上)または |
プラットフォーム非依存の整数型
プラットフォーム非依存の整数型は、使用するプラットフォームにかかわらず、常に同じサイズです。プラットフォーム非依存の整数型には、ShortInt、SmallInt、LongInt、Integer、Int64、Byte、Word、LongWord、Cardinal、UInt64 があります。
プラットフォーム非依存の整数型
| 型 | 値の範囲 | 形式 | エイリアス |
|---|---|---|---|
|
|
符号付き 8 ビット |
||
|
|
符号付き 16 ビット |
||
|
|
符号付き 32 ビット |
||
|
|
符号付き 32 ビット |
||
|
|
符号付き 64 ビット |
||
|
|
符号なし 8 ビット |
||
|
|
符号なし 16 ビット |
||
|
|
符号なし 32 ビット |
||
|
|
符号なし 32 ビット |
||
|
|
符号なし 64 ビット |
一般に、整数に対する算術演算は Integer 型の値を返します。これは、32 ビットの LongInt と同じです。演算が Int64 型の値を返すのは、1 つまたは複数の Int64 オペランドを実行した場合だけです。したがって、次のコードは不正な結果を返します。
var I: Integer; J: Int64; ... I := High(Integer); J := I + 1;
この状況で Int64 の戻り値を取得するには、I を Int64 に型キャストします。
... J := Int64(I) + 1;
詳細は、「算術演算子」を参照してください。
メモ: 整数引数をとる標準ルーチンには、Int64 を 32 ビットに切り捨てるものがあります。ただし、High、Low、Succ、Pred、Inc、Dec、IntToStr、および IntToHex ルーチンは、Int64 引数を完全にサポートします。また、Round、Trunc、StrToInt64、および StrToInt64Def 関数は、Int64 値を返します。一部のルーチンは Int64 の値をまったく受け取ることができません。
整数型の最後の値をインクリメントすると範囲の最初の値に、最初の値をデクリメントすると最後の値に戻ります。たとえば、ShortInt 型の範囲は -128~127 です。したがって、次のコードを実行すると、
var I: Shortint; ... I := High(Shortint); I := I + 1;
I の値は -128 になります。ただし、コンパイラによる範囲検査を有効にしている場合は、このコードを実行すると実行時エラーが発生します。
文字型
文字型には、Char、AnsiChar、WideChar、UCS2Char、UCS4Char があります。
- 現在の実装では、デフォルトの文字列型が UnicodeString であるため、Char は WideChar と同等です。Char の実装は今後のリリースで変更されることがあるため、サイズの異なる文字を処理しなければならない可能性のあるプログラムを作成するときは、定数をハードコードするのではなく、標準関数 SizeOf を使用した方がよいでしょう。
- AnsiChar 値は、ロケール文字セット(場合により、マルチバイト)に従って順序付けされたバイトサイズ(8 ビット)の文字です。
- WideChar 文字は、複数バイトを使用して、あらゆる文字を表します。現在の実装では、WideChar は、Unicode 文字セットに従って順序付けされたワードサイズ(16 ビット)の文字です(今後の実装では、サイズがもっと大きくなる可能性があります)。Unicode の先頭から 256 文字が ANSI 文字に対応します。
- UCS2Char は WideChar のエイリアスです。
- UCS4Char は、4 バイトの Unicode 文字を扱う場合に使用されます。
長さが 1 の文字列定数("A" など)は、文字値を表すことができます。定義済み関数 Chr は、WideChar(たとえば、Chr(65) は文字 A を返す)の範囲の整数に対応する文字値を返します。
整数と同様に、AnsiChar と WideChar の値は範囲の先頭をデクリメントすると範囲の末尾に、末尾をインクリメントすると先頭に戻ります(範囲検査を有効にしていない場合)。たとえば、次のコードを実行したとします。
var Letter: AnsiChar; I: Integer; begin Letter := High(Letter); for I := 1 to 66 do Inc(Letter); end;
実行後の Letter の値は A(ASCII 65)です。
論理型
4 つの定義済みの論理型として、Boolean、ByteBool、WordBool、および LongBool があります。Boolean が通常使用される型です。他の 3 つの型は、他の言語やオペレーティング システムのライブラリとの互換性を提供するために用意されています。
変数のサイズは、Boolean 変数と ByteBool 変数が 1 バイト、WordBool 変数が 2 バイト(1 ワード)、LongBool 変数が 4 バイト(2 ワード)です。
論理値は定義済みの定数 True と False で表されます。次の関係が成立します。
| Boolean | ByteBool、WordBool、LongBool |
|---|---|
|
False < True |
False <> True |
|
Ord(False) = 0 |
Ord(False) = 0 |
|
Ord(True) = 1 |
Ord(True) <> 0 |
|
Succ(False) = True |
Succ(False) = True |
|
Pred(True) = False |
Pred(False) = True |
ByteBool 型、LongBool 型、または WordBool 型の値は、順序値がゼロ以外の場合、True とみなされます。Boolean が予期される状況でこれらの値が使用された場合、コンパイラは順序値がゼロ以外の値を自動的に True に変換します。
なお、これは論理値の順序値に関する説明であり、論理値そのものに関するものではありません。Delphi では論理型の式を整数や実数と等価にみなすことはできません。X が整数変数であるときに、次のステートメントを記述したとします。
if X then ...;
これは、コンパイル エラーになります。この変数を論理型に型キャストしても結果は保証されませんが、以下の方法を使用すると問題を解決できます。
if X <> 0 then ...; { use an expression that returns Boolean value }
...
var OK: Boolean; { use Boolean variable }
...
if X <> 0 then
OK := True;
if OK then ...;
列挙型
列挙型では、値を表す識別子を列挙して、順序付けされた値の集合を定義します。値そのものが意味を持つものではありません。列挙型を宣言するには、次の構文を使用します。
type typeName = (val1, ...,valn)
typeName と val には有効な識別子を指定します。たとえば、次の宣言があるとします。
type Suit = (Club, Diamond, Heart, Spade);
これは、Suit という列挙型を定義しています。有効な値は、Club、Diamond、Heart、および Spade です。Ord(Club) は 0 を Ord(Diamond) は 1 を返します。
列挙型を宣言すると、それぞれの val が typeName という型の定数であることが宣言されます。val の識別子が同じスコープ内で別の目的に使用されている場合は、名前の競合が発生します。たとえば、次の型を宣言したとします。
type TSound = (Click, Clack, Clock)
残念ながら、Click は TControl と VCL 内のすべての下位オブジェクトで定義されているメソッドの名前でもあります。アプリケーションを作成するときに次のようなイベント ハンドラを書いたとします。
procedure TForm1.DBGridEnter(Sender: TObject);
var
Thing: TSound;
begin
...
Thing := Click;
end;
これは、コンパイル エラーになります。コンパイラは、手続きのスコープ内の Click を TForm の Click メソッドへの参照と解釈します。これは、識別子を修飾することによって対処できます。たとえば、TSound が MyUnit の中で宣言されている場合は、次のステートメントを使用します。
Thing := MyUnit.Click;
ただし、他の識別子と競合する可能性が少ない定数名を選択する方が、解決策としては優れています。以下に例を示します。
type TSound = (tsClick, tsClack, tsClock); TMyColor = (mcRed, mcBlue, mcGreen, mcYellow, mcOrange); Answer = (ansYes, ansNo, ansMaybe)
(val1, ..., valn) という構文は、型の名前と同じように変数宣言で直接使用できます。
var MyCard: (Club, Diamond, Heart, Spade);
しかし、この方法で MyCard を宣言すると、同じ定数識別子を使って同一スコープ内で別の変数を宣言できません。次のコードがあるとします。
var Card1: (Club, Diamond, Heart, Spade); var Card2: (Club, Diamond, Heart, Spade);
これは、コンパイル エラーになります。しかし、
var Card1, Card2: (Club, Diamond, Heart, Spade);
これは正しくコンパイルされます。次も同様です。
type
Suit = (Club, Diamond, Heart, Spade);
var
Card1: Suit;
Card2: Suit;
明示的に順序値を割り当てられた列挙型
デフォルトでは、列挙型の値の順序値は 0 から始まり、型宣言で識別子を記述したときと同じ順序になります。これを明示的にオーバーライドするには、宣言において一部またはすべての値に順序値を割り当てます。順序値を割り当てるには、その識別子の後に = constantExpression を記述します。ここで、constantExpression は、整数と評価される定数式です。たとえば、次のとおりです。
type Size = (Small = 5, Medium = 10, Large = Small + Medium);
これは、Size という型を定義します。有効な値は、Small、Medium、および Large です。Ord(Small) は 5、Ord(Medium) は 10、Ord(Large) は 15 を返します。
列挙型は本質的には部分範囲型であり、その上限と下限の値は、宣言における定数の順序値の上限と下限の値によって決まります。上の例で Size 型が取ることのできる値は 11 個で、順序値の範囲は 5 ~ 15 です。したがって、array[Size] of Char 型は、11 文字の配列を表します。上記の例では、3 つの値にのみ名前があります。ただし、他の値は、型キャストや Pred、Succ、Inc、Dec などのルーチンを通してアクセス可能です。次の例では、Size の範囲内の "無名" 値が変数 X に割り当てられています。
var X: Size; X := Small; // Ord(X) = 5 X := Size(6); // Ord(X) = 6 Inc(X); // Ord(X) = 7
順序値が明示的に割り当てられていない値は、リストの中の直前の値の順序値より 1 つ大きい値になります。最初の値に順序値が割り当てられていない場合は、その順序値は 0 になります。したがって、次のように宣言した場合、
type SomeEnum = (e1, e2, e3 = 1);
SomeEnum の有効な値は 2 つだけです。Ord(e1) は 0 を返し、Ord(e2) は 1 を返し、Ord(e3) も 1 を返します。e2 と e3 は同じ順序値で、同じ値を表します。
列挙型定数で値を指定しない場合、実行時型の情報をとります。
type SomeEnum = (e1, e2, e3);
それに対して、以下のように列挙型定数で値を指定する場合、実行時型の情報はとりません。
type SomeEnum = (e1 = 1, e2 = 2, e3 = 3);
スコープのある列挙型
$SCOPEDENUMS コンパイル指令を有効にすると、Delphi のコードでスコープのある列挙型を使用できます。
スコープのある列挙型は、列挙型要素への参照の先頭に型名を付けることで特徴付けられます。たとえば、次のユニットとプログラムで、スコープのある列挙型 TMyEnum で変数 Value の代入が可能になる方法("First" だけを指定すると、型の不一致エラーが発生する可能性がある場合)を確認できます。
unit Unit1;
interface
type
TMyEnum = (first, second, third);
implementation
end.
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,
Unit1 in 'Unit1.pas';
var
First: Integer;
Value: TMyEnum;
begin
try
Value := TMyEnum.First;
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
end.
部分範囲型
部分範囲型は、別の順序型の値の部分集合を表します。部分集合の基となる順序型は基底型と呼ばれます。Low と High が同じ順序型の定数式であり、Low が High より小さい場合、Low..High という形式の構文は Low から High までのすべての値を含む部分範囲型を表します。たとえば、次の列挙型を宣言したとします。
type TColors = (Red, Blue, Green, Yellow, Orange, Purple, White, Black);
この場合は、次のような部分範囲型を定義できます。
type TMyColors = Green..White;
ここで、TMyColors の値は、Green、Yellow、Orange、Purple、および White です。
数値定数と文字(長さが 1 の文字列定数)を使って部分範囲型を定義することもできます。
type SomeNumbers = -128..127; Caps = 'A'..'Z';
数値定数や文字定数を使って部分範囲型を定義するときは、指定した範囲を含む最小の整数型または文字型が基底型になります。
LowerBound..UpperBound という構文はそれ自体が型の名前として機能するので、変数の宣言で直接使用できます。たとえば、次のとおりです。
var SomeNum: 1..500;
これは 1 ~ 500 の範囲の任意の値をとる整数変数を宣言します。
部分範囲型の各値の順序値には、基底型における順序値が使用されます。最初の例では、変数 Color に Green という値が格納されている場合、Color の型が TColors であるか TMyColors であるかに関係なく、Ord(Color) は 2 を返します。部分範囲型の先頭または末尾を超えてインクリメントまたはデクリメントを実行した場合は、基底型が整数型または文字型の場合でも、値が部分範囲の末尾または先頭に戻ることはありません。値の型が部分範囲型から基底型に変換されるだけです。次のコードがあるとします。
type Percentile = 0..99; var I: Percentile; ... I := 100;
ここではエラーが発生します。
... I := 99; Inc(I);
これは、値 100 を I に代入します(コンパイラの範囲検査が有効ではない場合)。
部分範囲の定義で定数式を使用すると、構文上の問題が発生する場合があります。型宣言で = の次の文字(意味を持つ)が左かっこである場合、コンパイラは列挙型が定義されているものとみなします。次のコードがあるとします。
const X = 50; Y = 10; type Scale = (X - Y) * 2..(X + Y) * 2;
ここではエラーが発生します。この問題を回避するには、次のとおり先頭がかっこにならないように型宣言を書き換えます。
type Scale = 2 * (X - Y)..(X + Y) * 2;
実数型
実数型は、浮動小数点表記で表すことができる数の集合を定義します。以下の表では、64 ビット プラットフォームと 32 ビット プラットフォームにおける実数型の値の範囲と格納形式を示します。
実数型
| 型 | 正の値の範囲(概数) | 有効桁数 | サイズ(バイト数) |
|---|---|---|---|
| Real48 | 2.9e-39 .. 1.7e+38
|
11-12 | 6 |
| Single | 1.5e-45 .. 3.4e+38
|
7-8 | 4 |
| Double | 5.0e-324 .. 1.7e+308
|
15-16 | 8 |
| Real | 5.0e-324 .. 1.7e+308
|
15-16 | 8 |
| Extended |
|
10-20 15-16 |
10 8 |
| Comp | -263+1 .. 263-1
|
10-20 | 8 |
| Currency | -922337203685477.5808.. 922337203685477.5807
|
10-20 | 8 |
以下の備考は実数型に関するものです。
- Real48 は下位互換性のために維持されています。この型の格納形式は Intel プロセッサ アーキテクチャにネイティブではないため、結果的に、他の浮動小数点型よりもパフォーマンスが低くなります。
- 以前のバージョンの Object Pascal では、6 バイトの Real48 型は Real と呼ばれていました。以前の 6 バイトの Real 型を使用しているコードを Delphi で再コンパイルする場合は、Real48 に変更するとよいでしょう。また、{$REALCOMPATIBILITY ON} コンパイラ指令を使用して、Real を 6 バイトの型に戻すこともできます。
- Extended は、32 ビット プラットフォームでは、他の実数型よりも精度が高くなります。
- 64 ビット プラットフォームでは、Extended は Double のエイリアスです。つまり、Extended データ型のサイズは 8 バイトになります。したがって、64 ビット プラットフォームで Extended を使用すると、32 ビット プラットフォームの場合(Extended のサイズは 10 バイト)と比べて、精度が低くなります。そのため、アプリケーションで Extended データ型を使用していて、浮動小数点演算の精度に頼っている場合は、サイズのこのような違いがデータに影響を及ぼすおそれがあります。プラットフォーム間で共有するデータ ファイルを作成する場合は、Extended の使用に注意してください。詳細は、「64 ビット Windows システムでは Extended データ型のサイズは 2 バイト小さい」を参照してください。
- Comp 型はインテルのプロセッサ構造にネイティブで、64 ビットの整数を表します。しかし、この型は順序型と動作が異なるので、実数型に分類されています (たとえば、Comp 型の値をインクリメントまたはデクリメントできません)。Comp は下位互換性のためだけにサポートされています。Int64 を使用するとより優れた性能が得られます。
- Currency 型は、金額計算での丸め誤差が非常に少ない固定小数点データ型です。これは最下位 4 桁が暗黙に小数点以下の桁を表す位取り 64 ビット整数として格納されます。代入文や式で他の実数型と混在させた場合は、Currency 型の値に対して自動的に 10,000 での除算または乗算が行われます。