言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

Pascal辞典

  1. トップページ
  2. Pascal辞典
  3. RECORD 型(構造体)

RECORD 型(構造体)

『Pascal』の RECORD 型は、異なる型のフィールドを一つの複合データとしてまとめる仕組みです。C 言語の struct に相当します。フィールドにはどんな型でも使え、配列や別のレコード型を入れ子にすることもできます。宣言した変数にはドット(.)でフィールドへアクセスします。

構文

{ -----------------------------------------------
  RECORD 型の定義(TYPE セクション)
  ----------------------------------------------- }

type
  レコード型名 = record
    フィールド名1 : 型1;
    フィールド名2 : 型2;
    フィールド名3 : 型3;
  end;

{ -----------------------------------------------
  変数宣言と代入
  ----------------------------------------------- }

var
  変数名 : レコード型名;

begin
  変数名.フィールド名1 := 値1;
  変数名.フィールド名2 := 値2;
end.

{ -----------------------------------------------
  レコードの初期化(定数レコード)
  ----------------------------------------------- }

const
  定数名 : レコード型名 = (
    フィールド名1: 値1;
    フィールド名2: 値2
  );

構文一覧

構文 / キーワード概要
record ... endレコード型を定義するブロックです。type セクション内で使います。
変数.フィールド名ドット演算子でレコード変数のフィールドにアクセスします。
フィールドの型整数・実数・文字列・Boolean・列挙型・配列・別のレコード型など任意の型を使えます。
入れ子レコードフィールドの型に別のレコード型を指定することでレコードをネストできます。アクセスは 外.内.フィールド のように連鎖します。
定数レコードconst セクションで レコード型名 = (フィールド名: 値; ...) と書くと読み取り専用の初期値付きレコードを定義できます。
レコードの代入rec1 := rec2; で同じ型のレコード変数を丸ごとコピーできます。
配列との組み合わせarray[1..N] of レコード型 と宣言するとレコードの配列を作れます。arr[i].フィールド名 でアクセスします。
SizeOf(レコード型)レコード型全体のバイト数を返します。アライメントにより各フィールドのサイズの合計と異なる場合があります。

サンプルコード

sg_record.pas
{ sg_record.pas — Pascal の RECORD 型の基本を確認するサンプルです }
{ Steins;Gate のラボメンバーをレコード型で表現します }
{
  コンパイルと実行:
    fpc sg_record.pas && ./sg_record
}

program sg_record;

{ -----------------------------------------------
  ラボメンバーの役割を表す列挙型
  ----------------------------------------------- }
type
  TRole = (
    roleMadScientist,   { 狂気のマッドサイエンティスト }
    roleMoeGirl,        { ヒロイン枠(公式設定)}
    roleHacker,         { 技術担当ハッカー }
    roleNeuroscientist, { 神経科学者(未来人)}
    roleTimeTraveler    { 未来から来たタイムトラベラー }
  );

{ -----------------------------------------------
  ラボメンバー 1 人分のデータを格納するレコード型
  ----------------------------------------------- }
  TLabMember = record
    name        : string[40];  { 名前 }
    lab_id      : Integer;     { ラボメンバー番号 }
    role        : TRole;       { 役割 }
    ib_number   : string[20];  { IBN 5100 解析スキル(メモ文字列)}
    is_active   : Boolean;     { 現在ラボに在籍中かどうか }
  end;

{ -----------------------------------------------
  全メンバーをまとめる配列の要素数定数
  ----------------------------------------------- }
const
  MEMBER_COUNT = 5;

{ -----------------------------------------------
  役割を文字列に変換するヘルパー関数
  ----------------------------------------------- }
function RoleToStr(r: TRole): string;
begin
  case r of
    roleMadScientist  : RoleToStr := 'Mad Scientist';
    roleMoeGirl       : RoleToStr := 'Heroine';
    roleHacker        : RoleToStr := 'Hacker';
    roleNeuroscientist: RoleToStr := 'Neuroscientist';
    roleTimeTraveler  : RoleToStr := 'Time Traveler';
  end;
end;

{ -----------------------------------------------
  メンバー情報を整形して表示する手続き
  ----------------------------------------------- }
procedure PrintMember(m: TLabMember);
begin
  WriteLn('  No.', m.lab_id, '  ', m.name);
  WriteLn('       役割     : ', RoleToStr(m.role));
  WriteLn('       備考     : ', m.ib_number);
  if m.is_active then begin
    WriteLn('       在籍     : 在籍中');
  end else begin
    WriteLn('       在籍     : 離脱');
  end;
end;

var
  { -----------------------------------------------
    ラボメンバー配列の宣言
    ----------------------------------------------- }
  members : array[1..MEMBER_COUNT] of TLabMember;
  i       : Integer;
  copy_rec: TLabMember;  { レコードコピーの確認用 }

begin
  { -----------------------------------------------
    各メンバーのデータを設定します
    ----------------------------------------------- }

  { ラボメン 001 — 岡部倫太郎(Rintaro Okabe)}
  members[1].name      := 'Rintaro Okabe';
  members[1].lab_id    := 1;
  members[1].role      := roleMadScientist;
  members[1].ib_number := 'Reading Steiner 保持者';
  members[1].is_active := True;

  { ラボメン 002 — 椎名まゆり(Mayuri Shiina)}
  members[2].name      := 'Mayuri Shiina';
  members[2].lab_id    := 2;
  members[2].role      := roleMoeGirl;
  members[2].ib_number := 'コスプレ担当';
  members[2].is_active := True;

  { ラボメン 003 — 橋田至(Itaru Hashida)}
  members[3].name      := 'Itaru Hashida';
  members[3].lab_id    := 3;
  members[3].role      := roleHacker;
  members[3].ib_number := 'IBN 5100 解析担当';
  members[3].is_active := True;

  { ラボメン 004 — 牧瀬紅莉栖(Kurisu Makise)}
  members[4].name      := 'Kurisu Makise';
  members[4].lab_id    := 4;
  members[4].role      := roleNeuroscientist;
  members[4].ib_number := 'タイムリープマシン開発者';
  members[4].is_active := True;

  { ラボメン 006 — 阿万音鈴羽(Suzuha Amane)}
  members[5].name      := 'Suzuha Amane';
  members[5].lab_id    := 6;
  members[5].role      := roleTimeTraveler;
  members[5].ib_number := 'C204 操縦者(未来人)';
  members[5].is_active := False;  { 過去に出発済み }

  { -----------------------------------------------
    全メンバーの情報を表示します
    ----------------------------------------------- }
  WriteLn('===== Future Gadget Lab メンバー一覧 =====');
  for i := 1 to MEMBER_COUNT do begin
    PrintMember(members[i]);
    WriteLn('');
  end;

  { -----------------------------------------------
    レコードの丸ごとコピーを確認します
    ----------------------------------------------- }
  WriteLn('--- レコードコピー確認 ---');
  copy_rec := members[4];          { 牧瀬紅莉栖のデータをコピー }
  copy_rec.name := 'Copy of Kurisu';  { コピー先だけ名前を変更 }
  WriteLn('  コピー元 : ', members[4].name);
  WriteLn('  コピー先 : ', copy_rec.name);
  WriteLn('  コピー元は変更されていません(独立したコピー)');
  WriteLn('');

  { -----------------------------------------------
    SizeOf でレコードのバイト数を確認します
    ----------------------------------------------- }
  WriteLn('--- SizeOf 確認 ---');
  WriteLn('  SizeOf(TLabMember) = ', SizeOf(TLabMember), ' バイト');
  WriteLn('==========================================');
end.
fpc sg_record.pas && ./sg_record
Free Pascal Compiler version ...
Linking ./sg_record
===== Future Gadget Lab メンバー一覧 =====
  No.1  Rintaro Okabe
       役割     : Mad Scientist
       備考     : Reading Steiner 保持者
       在籍     : 在籍中

  No.2  Mayuri Shiina
       役割     : Heroine
       備考     : コスプレ担当
       在籍     : 在籍中

  No.3  Itaru Hashida
       役割     : Hacker
       備考     : IBN 5100 解析担当
       在籍     : 在籍中

  No.4  Kurisu Makise
       役割     : Neuroscientist
       備考     : タイムリープマシン開発者
       在籍     : 在籍中

  No.6  Suzuha Amane
       役割     : Time Traveler
       備考     : C204 操縦者(未来人)
       在籍     : 離脱

--- レコードコピー確認 ---
  コピー元 : Kurisu Makise
  コピー先 : Copy of Kurisu
  コピー元は変更されていません(独立したコピー)

--- SizeOf 確認 ---
  SizeOf(TLabMember) = 68 バイト
==========================================

よくあるミス

with 文との競合でどのレコードのフィールドかわからなくなる

with 文を使うと変数名の省略ができますが、複数のレコードを扱うコードでどのフィールドがどのレコードに属するかが読み取りにくくなることがあります。特に入れ子のレコードや複数の with を組み合わせる場合は、明示的にドット記法を使った方が意図が明確になります。

レコード配列の添字が範囲外になる

array[1..N] of レコード型 を宣言した場合、添字は 1 から N が有効です。0 や N+1 へのアクセスはコンパイルエラーにならず実行時エラーや不定動作になります。ループカウンタの初期値・終了値を宣言と合わせることが重要です。

異なるレコード型に同じフィールド名を使って混同する

複数のレコード型に同名のフィールドを定義した場合、代入先の型が異なるとコンパイルエラーになります。型は一致していても別のレコード型同士は互換性がないため、rec1 := rec2 のような代入は同じ型の変数間でのみ行えます。

概要

『Pascal』の RECORD 型はフィールドをドット(.)でアクセスする複合型で、C の struct に相当します。代入演算子 := でレコード全体を丸ごとコピーでき、コピー後のフィールド変更は元のレコードに影響しません(値コピー)。フィールドに別のレコード型を入れ子にしたり、array[1..N] of レコード型 で配列化するなど、柔軟なデータ構造を作れます。RECORD のフィールドアクセスを簡略化する WITH 文については WITH文(レコードフィールドの簡略アクセス) を、同一メモリを複数の型で共有するバリアントレコードについては バリアントレコード(CASE付きRECORD) も合わせて参照できます。ポインタとレコードを組み合わせた動的データ構造の例は ポインタを使ったリンクリストの実装 も参照できます。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。