Go to Nazona Web Site

謎奈の泉 > Delphi Memo Pad > Delphiで共用体

Memo List content pic
エラーの話 その1
Delphiで共用体
タスクバーボタンを非表示に

関連コンテンツ content pic
ソフトウェア
プログラム掲示板
リンク集

戻る content pic
謎奈の泉 トップページ
Delphiで共用体 index pic
■ 前書き
 Windowsアプリケーションの基本開発環境はVisual C++ですが、Delphiは非常に優れた開発環境だと思います。 Visual C++でできることはDelphiでも結構できるのです。私がVisual Basic 6.0を使っていた時は、 制限の多さに悩まされたものです。
 DelphiでWindowsアプリケーションを作ることは、VC++やVB6でそれを作るより、 ずっと効率のよいことだと、私は思っています。

 ところで、私のプログラムでは、Windows APIを使わないことはまずありません。 いくらDelphiがVisual C++と同じようなことができるとはいえ、Windows APIに関する微妙な誤差には 結構悩まされます。レコード名しかり、ユニット名しかり、変数型しかり……。

 特に私が悩まされたのは、共用体を含む構造体を使うWindows APIでした。 共用体というのは、Delphi語訳すると、 レコードの可変部分または可変部分を持つレコードだそうです。 Delphiで共用体は使えないだろうと勝手に判断していた私は、どのようにして逃げようかと、 非常に悩みましたが、Delphiを甘く見ていました。ヘルプにも載っているくらいで、ちゃんと使えたのです。

 今回は、Delphiで使うことはめったにない、共用体のお話です。

■ 構文
type レコード型名 = record
  フィールドリスト1: フィールド型1;
  ...
  フィールドリストn: フィールド型n;
  case タグ: タグフィールド型 of
    定数リスト1: (可変部1);
    ...
    定数リストn: (可変部n);
end;
◆規則
1.レコードの宣言では、可変レコード部分はほかのフィールドよりも後に記述しなければならない。
2.可変部分のタグはオプションであり、任意の名前を指定できるが、コロン(:)を含めて省略してもよい。
3.タグフィールド型には、順序型の型識別子を指定する。
4.定数リストにはタグフィールド型の値を表す定数か、そのような定数のカンマ区切りのリストである。n個ある定数リストの中で,同じ値を2回以上使用してはならない。
5.フィールド型は、長い文字列型,動的配列型,Variant 型,またはインターフェース型であってはならないし、それらをを含む構造体であってもならないが、これらの型へのポインタは許容される。
6.可変部の書式は、普通のフィールド定義と同様であるが、()内に、複数のフィールドを定義してもよい。

と、文章で言ったところでよくわからないので、何パターンか例を書いてみます。

■ 構文例
implementation
{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
type
  TSampleUnion1 = record
    sVal: String[20];
    case TagName: Integer of  // 可変部はほかのフィールドより後
      0: (iVal: Integer);
      1: (uVal: Cardinal);
  end;

  TSampleUnion2 = record
    sVal: String[20];
    case Integer of  // タグ名は省略可能
      0: (iVal: Integer);
      1: (uVal: Cardinal);
  end;

  TSampleUnion3 = record
    sVal: String[20];
    case TagName: Boolean of  // 順序型なら定義可能
      True : (iVal: Integer);
      False: (uVal: Cardinal);
  end;

  TSampleUnion4 = record
    sVal: String[20];
    case Boolean of
      True : (iVal: Integer);
      False: (uVal: Cardinal;
              bVal: Byte;
              cVal: Char);   // 複数のフィールドも定義可能
  end;

  TSampleUnion5 = record    // 可変レコード部だけ別に定義すれば……↓
    case Boolean of
      True : (iVal: Integer);
      False: (uVal: Cardinal);
  end;
  TSampleRecord = record
    sVal: String[20];
    uni5: TSampleUnion5;     // 可変レコード型なら真ん中に定義可能
    iVal: Integer;
  end;

begin
  ...
end;

■ コード補完ウィンドウ
◆TSampleUnion1
varsVal : String[20];
varTagName : Integer;
variVal : Integer;
varuVal : Cardinal;
◆TSampleUnion2
varsVal : String[20];
variVal : Integer;
varuVal : Cardinal;
◆TSampleUnion3
varsVal : String[20];
varTagName : Boolean;
variVal : Integer;
varuVal : Cardinal;
◆TSampleUnion4
varsVal : String[20];
variVal : Integer;
varuVal : Cardinal;
varbVal : Byte;
varcVal : Char;
◆TSampleRecord
varsVal : String[20];
varuni5 : TSampleUnion5;
variVal : Integer;

■ 最後に
 共用体を知らない人、知って間もない人にとっては、共用体の存在意義がいまいち掴めないかもしれません。 私もプログラミングで使ったことはほとんどありませんが、共有体を使ってプログラムの効率化を図る方法はなんとなくわかります。
 たとえば、構造体や変数などを一括管理するという面では、非常に使えるだろうと思っています。 (というか、共有体はそういうためのもののはず)

 みなさんも、Delphiで共有体を利用して、プログラムの効率化を図ってみてはいかかでしょうか?
Write : 2004/12/25

Copyright (c) 2002-2004 謎奈 / うえちょこ All rights reserved.