Delphi Programming / Object Pascal  
                     
                [掲載 2014年02月17日] [更新 2019年04月30日] Delphi 一般・その他  
             
           
        
        
        
          
            
              変数やオブジェクトの初期値 
             
            
               動作確認等  
               Windows 7 U64(SP1) + Delphi XE(UP1) Pro 
             
           
        
        
         
         
        
         
         
         
         
         
        
         
         
        
          
            
               変数の初期値には注意が必要です. 
                  グローバル変数は,ポイント型とオブジェクト型の場合,nil に初期化されます.数値は 0 に初期化されます.1 文字の型である Char 型の変数は Null 文字に初期化されます.一方,イベントやメソッド内で定義したそれらのローカル変数は初期化されません. 
                  string 型の文字列変数は,グローバル変数もローカル変数も長さ 0 の空文字となります. 
                 下図はクラス変数の場合です.クラス変数もグローバル変数ですから初期化されます. 
 
             
           
        
         
        
         
        
          
            
               
              図1  
                クラス型変数の初期値 
             
           
        
         
        
copy code 
        
          unit  Unit1; 
interface  
uses  
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, StdCtrls; 
type  
  TMyClass = class  
  public  
    class  var  
    FHogeInt    : Integer; 
    FHogeButton : TButton; 
  end ; 
  TForm1 = class (TForm) 
    Button1: TButton; 
    procedure  Button1Click(Sender: TObject); 
  private  
    { Private 宣言 }  
  public  
    { Public 宣言 }  
  end ; 
var  
  Form1: TForm1; 
implementation  
{$R *.dfm}  
// ============================================================================= 
//   クラス型変数の初期値を確認 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
var  
  LText : String ; 
begin  
  LText := 'FHogeInt は '  + IntToStr(TMyClass.FHogeInt) + ' です' ; 
  if  TMyClass.FHogeButton = nil  then  begin  
    LText := LText + sLineBreak + 'FHogeButton は nil です' ; 
  end  else  begin  
    LText := LText + sLineBreak + 'FHogeButton は nil ではありません' ; 
  end ; 
  MessageBox(0 , PChar(LText), '結果' , MB_ICONINFORMATION); 
end ; 
end . 
         
         
         
        
          
            
              以下はローカル変数の場合を確認した結果です.テストに使用したコードは,ローカル変数として整数を定義していますが,その値は,下図のように,0 とはなりません. 
             
           
        
         
         
        
          
            
               
              図2  
                ローカルな整数型の変数の,初期化されていない値の例 
             
           
        
         
        
copy code 
        
          procedure  TForm1.Button1Click(Sender: TObject); 
var  
  Value : Integer; 
begin  
  MessageBox(0 , PChar(IntToStr(Value)), '情報' , MB_OK); 
end ; 
         
         
         
        
          
            
               次のコードは,TButton オブジェクトの変数をローカル変数として定義しています. 
                このコードを実行しても,TButton オブジェクトの実体 (インスタンス) は nil としては検出できません.もちろん Assigned(aBtn) は True となります. 
             
           
        
         
        
         
        
          
            
               
              図3  
                ローカルなオブジェクトが初期化されていない場合 
             
           
        
         
        
          
            
               上のダイアログを閉じると,下図のように例外が発生します. 
                これは,aBtn が生成されていないので,aBtn というオブジェクトのインスタンス (実体) は存在しません.その存在しないオブジェクトに対して操作したために発生します. 
                もし,aBtn が nil の場合,nil のオブジェクトに対する操作では例外も何も発生しません. 
             
           
        
         
         
        
          
            
               
              図4  
                生成されていないオブジェクトを操作すると例外が発生する 
             
           
        
         
        
copy code 
        
          procedure  TForm1.Button1Click(Sender: TObject); 
var  
  aBtn : TButton; 
begin  
  if  aBtn = nil  then  begin  
    MessageBox(0 , 'nil です' , '情報' , MB_OK); 
  end ; 
  if  aBtn <> nil  then  begin  
    MessageBox(0 , 'nil ではありません' , '情報' , MB_OK); 
  end ; 
  // ここで例外が発生する 
  // aBtnがnilの場合はエラーにならないが,操作は無効となる 
  aBtn.Caption := 'ABC' ; 
end ; 
         
         
        
         
         
         
        
         
         
        
          
            
               通常は,上のコードをコンパイルすると,次のような警告が表示されます. 
                オブジェクトのインスタンスを生成するコードが存在する場合,この表示が現れるかどうかは,オブジェクトのインスタンスを生成するコードを書く位置にもよります.  
             
           
        
         
        
          
[DCC 警告] Unit1.pas(63): W1036 変数 'aBtn' が初期化されていない可能性があります
 
         
         
         
        
          
            
               次のコードも「初期化されていない可能性があります」の警告が表示されます. 
                  ローカル変数は初期化されません.このコードでは LIntB に値が代入されない場合があります.したがって,LIntC の値も不定値になってしまうことがあります.これを避けるには,LIntB に何らかの初期値を代入しておきます.あるいは,条件分岐に else を追加して LIntB に,必ず値がセットされるようにします. 
                 上のコードもこのコードも,短いコードですから,すぐに判断できますが,実際のアプリ開発でこのようなコーディングをしてしまうと,予期しない結果となる可能性があります. 
 
             
           
        
         
        
          [DCC 警告] Unit1.pas(37): W1036 変数 'LIntB' が初期化されていない可能性があります 
         
         
        
copy code 
        
          procedure  TForm1.Button1Click(Sender: TObject); 
var  
  LIntA : Integer; 
  LIntB : Integer; 
  LIntC : Integer; 
begin  
  LIntA := 100 ; 
  if  LIntA > 100  then  begin  
    LIntB := 200 ; 
  end ; 
  //上の条件に合わない時にLIntBを使用すると問題が発生する可能性がある  
  LIntC := LIntB; 
end ; 
         
         
         
        
          
            
               上のコードのようにローカルな処理の最初に変数に初期値を代入すると,以下のようなヒントが表示されることがあります.この現象は,Delphi のパーションやコーディングにもよるようです.実際にその変数が使われていても表示さることがあります. 
 
             
           
        
         
        
          [DCC ヒント] Unit1.pas(30): H2077 'LIntA' に代入された値は使われていません 
         
         
        
         
         
         
        
         
         
        
          
            
               String 型の文字列変数は,グローバル変数もローカル変数も長さ 0 の空文字となります. 
                  問題は文字列の領域を確保したり長さを設定したりする場合です.Windwos API 
                  の関数類を使用する際には必要となることがあります. 
                  領域を確保しただけとか,長さを設定しただけだと,いわゆる「ゴミ」が入ることがあります.これはメモリ上の不定な領域の値なので,いつも同じ値とは限りません.また,全く入らないか,制御文字等の場合は表示されません.
 
             
           
        
         
         
        
          
            
               [備考 1] 
                  文字列やテキストを扱う Windows API の関数類では,引数の値の設定によって,必要なバッファのサイズ (バイト数または文字数) が取得できることがあります.  
                  そのバッファのサイズで文字列の長さを設定してから,実際にその Windows API で目的の文字列等を扱ったり取得ができます., 
 
             
           
        
         
        
          
            
               [備考 2] 
                  結果の文字列の「ゴミ」は,下に示すコードの実行結果の場合です.実際に「ゴミ」が入るかどうかは,領域を確保した後にどんな処理をするかにもよります.
 
             
           
        
         
         
        
          
            
               SetLength
                  手続きで String 型の文字列を格納するメモリ領域を確保する場合です. 
                  SetLength 手続きは確保したメモリ領域を初期化しません.FillChar 手続きを使用すると初期化できます.FillChar 手続きの第 1 引数には String 型の文字列の最初の文字を指定します.文字のインデックスを指定しないで変数を渡すと,String 型の変数として機能しなくなります. 
 
             
           
        
         
         
        
          
            
               
              図5  
                SetLength で String 型の変数用のメモリを確保
                 
             
            
               
              図6  
                SetLength で String 型の変数用のメモリを確保
                 
             
           
        
         
        
copy code 
        
          // ============================================================================= 
//   SetLength で確保した String 型の変数の値は未定義状態 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
var  
  LString : string ; 
  LIndex  : Integer; 
begin  
  Memo1.Lines.Clear; 
  Memo1.Lines.BeginUpdate; 
  SetLength(LString, 100 ); 
  Memo1.Lines.Add(LString); 
  for  LIndex := 1  to  Length(LString) do  begin  
    Memo1.Lines.Add(IntToStr(LIndex) + ' : '  + LString[LIndex]); 
  end ; 
  Memo1.Lines.EndUpdate; 
end ; 
// ============================================================================= 
//   SetLength で確保した String 型の変数の初期化 
//   FillChar 手続きを使用して初期化できる 
// ============================================================================= 
procedure  TForm1.Button2Click(Sender: TObject); 
var  
  LString : string ; 
  LIndex  : Integer; 
begin  
  Memo1.Lines.Clear; 
  Memo1.Lines.BeginUpdate; 
  SetLength(LString, 100 ); 
  //  インデックス 1 を指定して初期化する 
  //  インデックスを指定しないと String 型の変数として機能しなくなる 
  FillChar(LString[1 ], Length(LString) * SizeOf(Char), #0 ); 
  Memo1.Lines.Add(LString); 
  for  LIndex := 1  to  Length(LString) do  begin  
    Memo1.Lines.Add(IntToStr(LIndex) + ' : '  + LString[LIndex]); 
  end ; 
  Memo1.Lines.EndUpdate; 
end ; 
         
         
         
        
          
            
               PChar 型の文字列変数用のメモリを確保する場合です.
                  AllocMem 関数を使用してメモリ領域を確保すると,そのメモリ領域を初期化してくれます.  
                  ZeroMemory 手続きや
                  FillChar
                  手続きを使用すると,確保したメモリ領域を初期化できます. 
 
             
           
        
         
         
        
          
            
               
              図7  
                PChar 型の文字列変数用のメモリの確保
                
                  StrAlloc 関数を使用した場合 
                  メモリは初期化されない 
                  
             
            
               
              図8  
                PChar 型の文字列変数用のメモリの確保
                
                  AllocMem 関数を使用した場合 
                  確保したメモリが初期化される 
                  
             
           
        
         
        
copy code 
        
          // ============================================================================= 
//   PChar 型の変数のメモリの確保に StrAlloc 関数を使用した場合 
//   確保したメモリ領域は初期化されない 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
var  
  LPChar : PChar; 
  LLen   : Integer; 
  LIndex : Integer; 
begin  
  Memo1.Lines.Clear; 
  Memo1.Lines.BeginUpdate; 
  LLen := 100 ; 
  //  メモリの確保 (+1 は Null 終端文字用) 
  LPChar := StrAlloc(LLen + 1 ); 
  try  
   //  途中で初期化したい場合は以下のどちらかを実行 
   //  ZeroMemory(LPChar, (LLen + 1) * SizeOf(Char)); 
   //  FillChar(LPChar[0], (LLen + 1) * SizeOf(Char), #0); 
    Memo1.Lines.Add(LPChar); 
    for  LIndex := 0  to  LLen - 1  do  begin  
      Memo1.Lines.Add(IntToStr(LIndex) + ' : '  + LPChar[LIndex]); 
    end ; 
  finally  
    StrDispose(LPChar); 
  end ; 
  Memo1.Lines.EndUpdate; 
end ; 
// ============================================================================= 
//   PChar 型の変数のメモリの確保に AllocMemc 関数を使用した場合 
//   確保したメモリ領域が初期化される 
// ============================================================================= 
procedure  TForm1.Button2Click(Sender: TObject); 
var  
  LPChar : PChar; 
  LLen   : Integer; 
  LIndex : Integer; 
begin  
  Memo1.Lines.Clear; 
  Memo1.Lines.BeginUpdate; 
  LLen := 100 ; 
  //  メモリの確保 (+1 は Null 終端文字用) 
  LPChar := AllocMem((LLen + 1 ) * SizeOf(Char)); 
  try  
   //  途中で初期化したい場合は以下のどちらかを実行 
   //  ZeroMemory(LPChar, (LLen + 1) * SizeOf(Char)); 
   //  FillChar(LPChar[0], (LLen + 1) * SizeOf(Char), #0); 
    Memo1.Lines.Add(LPChar); 
    for  LIndex := 0  to  LLen - 1  do  begin  
      Memo1.Lines.Add(IntToStr(LIndex) + ' : '  + LPChar[LIndex]); 
    end ; 
  finally  
    FreeMem(LPChar); 
  end ; 
  Memo1.Lines.EndUpdate; 
end ; 
         
         
        
         
         
         
        
          
            
              04_ const 修飾子と型付き定数による初期化 - 値が変更できる定数 
             
           
        
         
         
        
          
            
               一般的に,ローカルな変数は,その変数を使用する前に,一定の値を代入したりして初期化しておくと確実です.また,オブジェクト型の場合は nil を代入しておくと,そのオブジェクトが nil かどうかを判定することができます. 
                 const 修飾子を使用すると変数を初期化できます.ただし,これは厳密には変数とは言えません.定数値です.次のような型付き定数を使用すると,初期値が設定でき,実行時にもその値を変数することができます.変更可能な定数ということになります. 
                  型付き定数の値を変更可能にするには,コンパイラ指令の {$WRITEABLECONST ON} または {$J+} が必要です.型付き定数の値を変更しないようにするには,{$WRITEABLECONST OFF} または {$J-} を指定します.これがデフォルトのコンパイラ指令となっています. 
 
             
           
        
         
        
         
        
copy code 
        
          // 通常の定数(const修飾子) 
const  
  ID_Valuea = 100 ; 
{$WRITEABLECONST ON}  
// 型付き定数 
const  
  ID_Value : Integer = 100 ; 
  ID_Array : array [0 ..3 ] of  Integer = (10 , 20 , 30 , 40 ); 
{$WRITEABLECONST OFF}  
         
         
         
        
          
            
              値の変更が可能な,型付き定数を使用する例です. 
                ID_Value という型付き定数の初期値は 100 ですが,実行時に 500 という値にしています. 
             
           
        
         
         
        
          
            
               
              図9  
                下のコードの実行結果 
             
           
        
         
        
copy code 
        
          implementation  
{$R *.dfm}  
{$WRITEABLECONST ON}  
// ============================================================================= 
//   型付き定数を使用した変数の初期化 
//   {$WRITEABLECONST ON}または{$J+}指令を使用すると型付き定数の値が変更できる 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
const  
  ID_Value : Integer = 100 ; 
var  
  LText : String ; 
begin  
  ID_Value := 500 ; 
  LText    := IntToStr(ID_Value); 
  MessageBox(Handle, PChar(LText), '結果' , MB_ICONINFORMATION); 
end ; 
         
         
         
        
          
            
              型付き定数は,その値を実行時に変更すると,たとえローカルな型付き定数であっても,その値を保持するようになっています.このことを利用したテストです. 
                このコードは,ボタンをクリックすると,定義した型付き定数の値をインクリメントして,そのクリック回数をボタンの Caption とします.回数は 10 回まで数えます. 
             
           
        
         
         
        
          
            
               
              図10  
                実行開始時の画面 
             
            
               
              図11  
                Button1 を 4 回クリックした結果 
             
            
               
              図12  
                Button1 を 11 回以上クリックした結果 
             
           
        
         
        
copy code 
        
          implementation  
{$R *.dfm}  
{$WRITEABLECONST ON}  
// ============================================================================= 
//   型付き定数を使用したサンプル 
//  
//   型付き定数は値の変更が可能 
//   型付き定数の値がローカル内でも保持されることを利用したカウンタの例 
//   ボタンクリックの回数を調べる 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
const  
  ID_Value : Integer = 0 ; 
begin  
  Inc(ID_Value); 
  if  ID_Value > 10  then  begin  
    Button1.Caption := 'クリック数が 10 回を超えています' ; 
  end  else  begin  
    Button1.Caption := 'クリック回数 : '  + IntToStr(ID_Value); 
  end ; 
end ; 
         
         
        
         
         
         
        
          
            
              05_ const 修飾子と型付き定数を使用したトグル操作ボタン 
             
           
        
         
         
        
          
            
               チェックボックスのようなトグル機能のボタンは,次のように,const 修飾子と型付き定数を利用して実装することができます.このコードはボタンクリックのイベント内にトグル状態を保持する変数がありますから,コードの見通しがいいと言えます. 
                 トグル状態をプログラムの他の場所で使用する必要がある場合は,フラグ用の Boolean 型 (論理型) のグローバル変数を用意して現在の状態をセットしておきます.そうすればその変数の値で現在の状態を判定できます. 
 
             
           
        
         
        
         
        
          
            
               
              図13  
                EXE 起動時の状態 
             
            
               
              図14  
                ボタンをクリックすると状態が変わる
                 
             
           
        
         
        
copy code 
        
          // ============================================================================= 
//   フォーム生成時の処理 
// ============================================================================= 
procedure  TForm1.FormCreate(Sender: TObject); 
begin  
  Button1.Caption := 'switch ON' ; 
end ; 
// ============================================================================= 
//   const 修飾子と型付き定数を使用したトグルボタン 
// ============================================================================= 
{$WRITEABLECONST ON}  
procedure  TForm1.Button1Click(Sender: TObject); 
const  
  LToggleON : Boolean = False; 
begin  
  if  not  LToggleON then  begin  
    Button1.Caption := 'switch OFF' ; 
  end  else  begin  
    Button1.Caption := 'switch ON' ; 
  end ; 
  // トグル 
  LToggleON := not  LToggleON; 
end ; 
{$WRITEABLECONST OFF}  
         
         
        
         
         
         
        
          
            
              06_ クラスのメンバーではないグローバル変数の初期化 
             
           
        
         
         
        
          
            
               次のように,クラスのメンバーではないグローバル変数は,定義の時に初期化できます. 
 
             
           
        
         
         
        
          
            
               
              図15  
                クラスのメンバでない変数は初期化できる 
             
           
        
         
        
copy code 
        
          implementation  
{$R *.dfm}  
var  
  FValue : Integer = 100 ; 
// ============================================================================= 
//   クラスのメンバでないグローバルな変数の操作 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
begin  
  FValue := FValue + 300 ; 
  MessageBox(Handle, PChar(IntToStr(FValue)), '結果' , MB_ICONINFORMATION); 
end ; 
         
         
        
         
         
         
        
         
         
        
          
            
               Char 方の文字配列は,上のサンプルでも使用している FillChar 手続きで初期化できます・ 
                  一般的に,配列の要素の値は,for next 等のループで初期化できますが,要素の値を全て 0 に初期化するのであれば ZeroMemory 手続きが利用できます. 
                  ZeroMemory 手続きによる初期化は,静的配列でも動的配列でも使用できます. 
                 ZeroMemory の第 2 引数には,その配列が使用しているバイト数を指定します.そのバイト数には,配列の要素数に,変数の型のバイトサイズを乗算した値を使用します.配列の要素数は Length 関数で取得できます.また,変数の型のバイトサイズは SizeOf 関数で取得できます. 
 
             
           
        
         
        
         
        
          
            
               
              図16  
                整数型の静的配列の要素を全て 0 にする 
             
           
        
         
        
copy code 
        
          // ============================================================================= 
//   整数型の静的配列の値を全て0にする 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
var  
  LData  : array [0 ..4 ] of  Integer; 
  LIndex : Integer; 
begin  
  ListBox1.Items.Clear; 
  ListBox1.Items.BeginUpdate; 
  // 値を代入 
  LData[0 ] := 0 ; 
  LData[1 ] := 100 ; 
  LData[2 ] := 200 ; 
  LData[3 ] := 300 ; 
  LData[4 ] := 400 ; 
  // 全ての要素を0にする 
  // 実は単にメモリの値を0にする操作 
  ZeroMemory(@LData[0 ], Length(LData) * SizeOf(Integer)); 
  // 確認表示 
  for  LIndex := Low(LData) to  High(LData) do  begin  
    ListBox1.Items.Add(Format('%6d' , [LData[LIndex]])); 
  end ; 
  ListBox1.Items.EndUpdate; 
end ; 
         
         
         
        
          
            
               グローバル変数として定義するか,型付き定数として定義した場合は,配列の各要素の値の初期値を設定できます. 
 
             
           
        
         
        
         
        
          
            
               
              図17  
                グローバル変数で定義した配列要素の値を取得 
             
            
               
              図18  
                型付き定数で定義した配列の要素の値を取得 
             
           
        
         
        
copy code 
        
          unit  Unit1; 
interface  
uses  
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, StdCtrls; 
type  
  TForm1 = class (TForm) 
    Button1: TButton; 
    Button2: TButton; 
    ListBox1: TListBox; 
    procedure  Button1Click(Sender: TObject); 
    procedure  Button2Click(Sender: TObject); 
    procedure  FormCreate(Sender: TObject); 
  private  
    { Private 宣言 }  
  public  
    { Public 宣言 }  
  end ; 
var  
  Form1: TForm1; 
implementation  
{$R *.dfm}  
var  
  FData : array [0 ..4 ] of  Integer = (0 , 100 , 200 , 300 , 400 ); 
// ============================================================================= 
//   フォーム生成時の処理 
// ============================================================================= 
procedure  TForm1.FormCreate(Sender: TObject); 
begin  
  ListBox1.Font.Name := 'Courier New' ; 
  ListBox1.Font.Size := 10 ; 
end ; 
// ============================================================================= 
//   グローバルな配列変数の要素を取得して表示 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
var  
  i : Integer; 
begin  
  ListBox1.Items.Clear; 
  ListBox1.Items.BeginUpdate; 
  for  i := Low(FData) to  High(FData) do  begin  
    ListBox1.Items.Add(Format('%6d' , [FData[i]])); 
  end ; 
  ListBox1.Items.EndUpdate; 
end ; 
// ============================================================================= 
//   ローカルな配列変数の要素を取得して表示 
//   constで定義すれば配列要素の値を初期設定可能 
// ============================================================================= 
procedure  TForm1.Button2Click(Sender: TObject); 
const  
  LData : array [0 ..4 ] of  Integer = (0 , 10 , 20 , 30 , 40 ); 
var  
  i : Integer; 
begin  
  ListBox1.Items.Clear; 
  ListBox1.Items.BeginUpdate; 
  for  i := Low(LData) to  High(LData) do  begin  
    ListBox1.Items.Add(Format('%6d' , [LData[i]])); 
  end ; 
  ListBox1.Items.EndUpdate; 
end ; 
end . 
         
         
        
         
         
         
        
         
         
        
          
            
               動的配列は,SetLength 手続きで要素数を確保するとデフォルトの値に初期化されます.ただし,それは初回だけです.2 回目以降の挙動についてはオンラインヘルプで確認してください. 
                 型宣言の動的配列であれば,InitializeArray 関数を使用して,その要素の値を初期化できます.ただし,値の指定はありません.デフォルトの初期値である 0 となります.上の静的配列の初期化のサンプルで使用した ZeroMemory 手続きでも 0 に初期化できます. 
                  下に示すコードは,TIntegerDynArray 型の整数配列の各要素の値を全て 0 にする例です. 
 
             
           
        
         
        
         
        
          
            
               
              図19  
                動的配列の要素の初期化例
                
                  各要素に値を代入した後,初期化したので全ての要素の値が 0 になっている 
                  
             
           
        
         
        
copy code 
        
          // ============================================================================= 
//   配列要素の初期化 
//   InitializeArray関数を使用 
//  
//   TIntegerDynArrayの使用にはusesにTypesが必要 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
var  
  Array1 : TIntegerDynArray; 
  i      : Integer; 
begin  
  Memo1.Lines.Clear; 
  // サイズを設定して各要素に値を代入 
  SetLength(Array1, 10 ); 
  for  i := Low(Array1) to  High(Array1) do  begin  
    Array1[i] := i; 
  end ; 
  // 配列の要素を初期化(全て0になる) 
  // InitializeArrayは要素数の設定はしないので注意 
  InitializeArray(Array1, TypeInfo(TIntegerDynArray), Length(Array1)); 
  // 確認表示 
  for  i := Low(Array1) to  High(Array1) do  begin  
    Memo1.Lines.Add(IntToStr(i) + ' --  '  + IntToStr(Array1[i])); 
  end ; 
end ; 
         
         
         
        
          
            
               動的配列のメモリの解放操作は特に必要ありませんが,明示的に解放するのであれば  Finalize 関数が使用できます. 
                  Finalize 関数は,配列が確保したメモリ領域を解放し,要素数を 0 にします.つまり,配列要素が設定されていない初期の状態にします.
 
             
           
        
         
        
         
        
          
            
               
              図20  
                動的配列を初期化すると要素数は 0 となる 
             
           
        
         
        
copy code 
        
          // ============================================================================= 
//   動的に割り当てた変数の初期化(1) 
//   Finalize関数を使用 
//   型宣言の動的配列 
//  
//   TIntegerDynArrayの使用にはusesにTypesが必要 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
var  
  Array1 : TIntegerDynArray; 
begin  
  Memo1.Lines.Clear; 
  // 配列の要素数を設定 
  SetLength(Array1, 10 ); 
  Memo1.Lines.Add('要素数 : '  + IntTostr(Length(Array1))); 
  // 配列の初期化(要素のサイズは0になる) 
  Finalize(Array1); 
  Memo1.Lines.Add('要素数 : '  + IntTostr(Length(Array1))); 
end ; 
// ============================================================================= 
//   動的に割り当てた変数の初期化(2) 
//   型宣言でない動的配列 
//   Finalize関数を使用 
// ============================================================================= 
procedure  TForm1.Button2Click(Sender: TObject); 
var  
  Array1 : array  of  Integer; 
begin  
  Memo1.Lines.Clear; 
  // 配列の要素数を設定 
  SetLength(Array1, 10 ); 
  Memo1.Lines.Add('要素数 : '  + IntTostr(Length(Array1))); 
  // 配列の初期化(要素のサイズは0になる) 
  Finalize(Array1); 
  Memo1.Lines.Add('要素数 : '  + IntTostr(Length(Array1))); 
end ; 
         
         
         
        
          
            
               動的配列では,そのコンストラクタで,動的配列要素の確保と同時に初期値の設定が可能です. 
 
             
           
        
         
        
         
        
         
         
         
        
          
            
              09_ バイト型配列 ( TBytes ) の要素の初期化 
             
           
        
         
         
        
          
            
               TBytes 型のバイト配列の要素も ZeroMemory 手続きを使用して初期化できます.この場合の初期化は,配列要素の各バイト値を全て $00 にします.FillMemory 手続きを使用すると全ての要素の値を $00 以外の同じ値にできます. 
                 配列が使用しているバイト数 (メモリサイズ) は,静的配列であれば SizeOf 関数で取得できます.動的配列の場合は,SizeOf 関数で取得した値は配列の型のサイズになります.動的配列の変数はポインタですから,これはポインタのサイズです.したがって,32 ビットの EXE では 4, 64 ビットの EXE てば 8 になります. 
                  動的なバイト配列が使用しているバイト数は Length 関数で取得できます. 
                 動的配列の要素数を SetLength 手続きで設定した場合,配列の要素は 0 または nil に初期化されます.バイト配列の場合は全ての要素の値が 0 になります. 
 
             
           
        
         
        
         
        
          
            
               
              図21  
                バイト型配列の要素の初期化
                 
             
           
        
         
        
copy code 
        
          // ============================================================================= 
//   バイト配列の初期化(全ての要素を 0にする) 
//   動的配列の場合 
//   ZeroMemory手続きを使用する例 
//  
//   ZeroMemory手続きにはLength 関数で取得したバイト長さを与える 
//   動的配列の場合,SizeOf で取得した値は型のサイズになる 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
var  
  LArrBytes : TBytes; 
  LIndex    : Integer; 
begin  
  Memo1.Lines.Clear; 
  SetLength(LArrBytes, 10 ); 
  //  初期化確認用に要素に値をセット 
  for  LIndex := Low(LArrBytes) to  High(LArrBytes) do  begin  
    LArrBytes[LIndex] := Byte(LIndex + 1 ); 
  end ; 
  //  配列の要素を初期化(全て0になる) 
  ZeroMemory(@LArrBytes[0 ], Length(LArrBytes)); 
  //  初期化後の各要素の値を確認表示 
  for  LIndex := Low(LArrBytes) to  High(LArrBytes) do  begin  
    Memo1.Lines.Add('$'  + IntToHex(LArrBytes[LIndex], 2 )); 
  end ; 
  Memo1.Lines.Add('SizeOf : ' + IntToStr(SizeOf(LArrBytes))); 
  Memo1.Lines.Add('Length : ' + IntToStr(Length(LArrBytes))); 
end ; 
// ============================================================================= 
//   バイト配列の初期化(全ての要素を同じ値にする) 
//   動的配列の場合 
//   FillMemory手続きを使用する例 
//  
//   FillMemory手続きにはLength 関数で取得したバイト長さを与える 
//   動的配列の場合,SizeOf で取得した値は型のサイズになる 
// ============================================================================= 
procedure  TForm1.Button2Click(Sender: TObject); 
var  
  LArrBytes : TBytes; 
  LIndex    : Integer; 
begin  
  Memo1.Lines.Clear; 
  SetLength(LArrBytes, 10 ); 
  //  初期化確認用に要素に値をセット 
  for  LIndex := Low(LArrBytes) to  High(LArrBytes) do  begin  
    LArrBytes[LIndex] := Byte(LIndex + 1 ); 
  end ; 
  //  配列の要素を初期化(全て同じ値になる) 
  FillMemory(@LArrBytes[0 ], Length(LArrBytes), $EE ); 
  //  初期化後の各要素の値を確認表示 
  for  LIndex := Low(LArrBytes) to  High(LArrBytes) do  begin  
    Memo1.Lines.Add('$'  + IntToHex(LArrBytes[LIndex], 2 )); 
  end ; 
  Memo1.Lines.Add('SizeOf : ' + IntToStr(SizeOf(LArrBytes))); 
  Memo1.Lines.Add('Length : ' + IntToStr(Length(LArrBytes))); 
end ; 
// ============================================================================= 
//   バイト配列の初期化(全ての要素を 0にする) 
//   静的配列の場合 
//   ZeroMemory手続きを使用する例 
//  
//   静的配列の場合は SizeOf 関数でバイト数を取得できる 
// ============================================================================= 
procedure  TForm1.Button3Click(Sender: TObject); 
var  
  LArrBytes : array  [0 ..9 ] of  Byte; 
  LIndex    : Integer; 
begin  
  Memo1.Lines.Clear; 
  //  初期化確認用に要素に値をセット 
  for  LIndex := Low(LArrBytes) to  High(LArrBytes) do  begin  
    LArrBytes[LIndex] := Byte(LIndex + 1 ); 
  end ; 
  //  配列の要素を初期化(全て0になる) 
  ZeroMemory(@LArrBytes[0 ], SizeOf(LArrBytes)); 
  //  初期化後の各要素の値を確認表示 
  for  LIndex := Low(LArrBytes) to  High(LArrBytes) do  begin  
    Memo1.Lines.Add('$'  + IntToHex(LArrBytes[LIndex], 2 )); 
  end ; 
  Memo1.Lines.Add('SizeOf : ' + IntToStr(SizeOf(LArrBytes))); 
  Memo1.Lines.Add('Length : ' + IntToStr(Length(LArrBytes))); 
end ; 
         
         
        
         
         
         
        
          
            
              10_ バイト列 ( PByte 型 ) データの初期化 
             
           
        
         
         
        
          
            
               PByte 型のバイト列データも ZeroMemory 手続きを使用して初期化できます.この場合の初期化は,バイト列データの値を全て $00 にします.  
                  FillMemory 手続きを使用すると,全てのバイト列のデータを特定のバイト値にできます. 
 
             
           
        
         
        
         
        
          
            
               
              図22  
                PByte 型のバイト列データ
                
                  これは初期化していない時の値 
                  ローカル変数なので初期化されていない 
                  
             
            
               
              図23  
                初期化した状態の PByte データ列の値
                 
             
           
        
         
        
copy code 
        
          // ============================================================================= 
//   バイト列テータの初期化 
//   GetMem 関数で領域を確保した場合は初期化されない 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
var  
  LPByte     : PByte; 
  LPByteDst  : PByte; 
  LBytevalue : Byte; 
  LSize      : Integer; 
  LIndex     : Integer; 
begin  
  Memo1.Lines.Clear; 
  Memo1.Lines.BeginUpdate; 
  // バイト列データ用のメモリ領域を確保 
  LSize  := 100 ; 
  GetMem(LPByte, LSize); 
  try  
    // 確認表示 
    // バイト列データを順番に取り出して表示 
    LPByteDst := LPByte; 
    for  LIndex := 0  to  LSize - 1  do  begin  
      LBytevalue :=  Byte(LPByteDst^); 
      Memo1.Lines.Add('$'  + IntToHex(LBytevalue, 2 )); 
      // バイト列のポインタをインクリメント 
      inc(LPByteDst); 
    end ; 
  finally  
    FreeMem(LPByte); 
  end ; 
  Memo1.Lines.EndUpdate; 
end ; 
// ============================================================================= 
//   バイト列テータの初期化 
//   GetMem 関数で領域を確保した場合は初期化されない 
//   ZeroMemory 手続きでバイト列データを 0 に初期化する例 
// ============================================================================= 
procedure  TForm1.Button2Click(Sender: TObject); 
var  
  LPByte     : PByte; 
  LPByteDst  : PByte; 
  LBytevalue : Byte; 
  LSize      : Integer; 
  LIndex     : Integer; 
begin  
  Memo1.Lines.Clear; 
  Memo1.Lines.BeginUpdate; 
  // バイト列データ用のメモリ領域を確保 
  LSize  := 100 ; 
  GetMem(LPByte, LSize); 
  try  
    //  バイト列のデータを初期化(全て0になる) 
    ZeroMemory(LPByte, LSize); 
    // 確認表示 
    // バイト列データを順番に取り出して表示 
    LPByteDst := LPByte; 
    for  LIndex := 0  to  LSize - 1  do  begin  
      LBytevalue :=  Byte(LPByteDst^); 
      Memo1.Lines.Add('$'  + IntToHex(LBytevalue, 2 )); 
      // バイト列のポインタをインクリメント 
      inc(LPByteDst); 
    end ; 
  finally  
    FreeMem(LPByte); 
  end ; 
  Memo1.Lines.EndUpdate; 
end ; 
         
         
         
        
          
            
               上のサンプルではバイト列データ用のメモリ領域の確保に GetMem 関数を使用しています. 
                  次のように,メモリの確保に AllocMem 関数を使用すると,確保したメモリ領域を 0 に自動で初期化してくれます. 
 
             
           
        
         
         
        
          
            
               
              図24  
                AllocMem 関数でメモリ領域を確保した場合
                 
             
           
        
         
        
copy code 
        
          
// ============================================================================= 
//   バイト列テータの初期化 
//   AllocMem 関数で領域を確保した場合は 0 に初期化される 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
var  
  LPByte     : PByte; 
  LPByteDst  : PByte; 
  LBytevalue : Byte; 
  LSize      : Integer; 
  LIndex     : Integer; 
begin  
  Memo1.Lines.Clear; 
  Memo1.Lines.BeginUpdate; 
  // バイト列データ用のメモリ領域を確保 
  LSize  := 100 ; 
  LPByte := AllocMem(LSize); 
  try  
    // 確認表示 
    // バイト列データを順番に取り出して表示 
    LPByteDst := LPByte; 
    for  LIndex := 0  to  LSize - 1  do  begin  
      LBytevalue :=  Byte(LPByteDst^); 
      Memo1.Lines.Add('$'  + IntToHex(LBytevalue, 2 )); 
      // バイト列のポインタをインクリメント 
      inc(LPByteDst); 
    end ; 
  finally  
    FreeMem(LPByte); 
  end ; 
  Memo1.Lines.EndUpdate; 
end ; 
         
         
        
         
         
         
        
         
         
        
          
            
               Char 型の文字配列の要素も ZeroMemory 手続きを使用して初期化できますが,Char 型の文字配列の場合は専用の FillChar という手続きがあります. 
                  静的な Char 型の文字配列で 
                  FillChar 手続きを使用する場合,第 2 引数に必要なバイト数は SizeOf 関数で取得できます. 
                 動的な Char 型の文字配列が使用しているバイト数は,Length(配列の変数名) * SizeOf(Char) という計算式で取得できます.  
                  動的な Char 型文字配列の場合,SizeOf 関数で取得した値は,配列の型のサイズになります.動的配列の変数はポインタですから,これはポインタのサイズです.したがって,32 ビットの EXE では 4, 64 ビットの EXE てば 8 になります. 
                 FillChar 手続きの最後の 3 番目の引数は 1 バイトイトの整数または AnsiString 型の半角文字 (ASCII 文字) です.2 バイトの値を渡しても,実際に使用されるのは下位バイトだけです. 
                 Char型の動的配列は,SetLength
                  関数で初期化されます.SetLength 手続きでサイズを拡張した場合,拡張前の要素のデータはそのまま残ります.拡張した部分は初期化状態となります. 
                  改めて初期化する時に FillChar 手続きが使用できます. 
 
             
           
        
         
         
        
          
            
               
              図25  
                Char 型の動的配列要素の初期化例
                 
             
           
        
         
        
copy code 
        
          // ============================================================================= 
//   Char型の文字配列の初期化(全ての要素を Null 文字にする) 
//   Char型の静的配列の場合 
//   FillChar手続きを使用する例 
//  
//   FillChar 手続きの第 2 引数はバイト数 
//   静的配列の場合は SizeOf 関数でバイト数を取得できる 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
var  
  LArrChar  : array  [0 ..9 ] of  Char; 
  LIndex  : Integer; 
begin  
  Memo1.Lines.Clear; 
  //  初期化確認用に要素に値をセット 
  for  LIndex := Low(LArrChar) to  High(LArrChar) do  begin  
    LArrChar[LIndex] := Char((LIndex * 2 ) + $3042 ); 
  end ; 
  Memo1.Lines.Add(LArrChar); 
  //  初期化(全て Null 文字になる) 
  FillChar(LArrChar[0 ], SizeOf(LArrChar), #0 ); 
  //  初期化後の各要素の値を確認表示 
  for  LIndex := Low(LArrChar) to  High(LArrChar) do  begin  
    Memo1.Lines.Add('$'  + IntToHex(Ord(LArrChar[LIndex]), 4 )); 
  end ; 
  Memo1.Lines.Add('SizeOf : ' + IntToStr(SizeOf(LArrChar))); 
  Memo1.Lines.Add('Length * 2 : ' + IntToStr(Length(LArrChar) * SizeOf(Char))); 
end ; 
// ============================================================================= 
//   Char型の文字配列の初期化(全ての要素を Null 文字にする) 
//   Char型の静的配列の場合 
//   ZeroMemory手続きを使用する例 
//  
//   ZeroMemory手続きの引数にはバイト数が必要 
// ============================================================================= 
procedure  TForm1.Button2Click(Sender: TObject); 
var  
  LArrChar : array  [0 ..9 ] of  Char; 
  LIndex   : Integer; 
begin  
  Memo1.Lines.Clear; 
  //  初期化確認用に要素に値をセット 
  for  LIndex := Low(LArrChar) to  High(LArrChar) do  begin  
    LArrChar[LIndex] := Char((LIndex * 2 ) + $3042 ); 
  end ; 
  Memo1.Lines.Add(LArrChar); 
  //  初期化(全て Null 文字になる) 
  ZeroMemory(@LArrChar[0 ], Length(LArrChar) * SizeOf(Char)); 
  //  初期化後の各要素の値を確認表示 
  for  LIndex := Low(LArrChar) to  High(LArrChar) do  begin  
    Memo1.Lines.Add('$'  + IntToHex(Ord(LArrChar[LIndex]), 4 )); 
  end ; 
  Memo1.Lines.Add('SizeOf : ' + IntToStr(SizeOf(LArrChar))); 
  Memo1.Lines.Add('Length * 2 : ' + IntToStr(Length(LArrChar) * SizeOf(Char))); 
end ; 
// ============================================================================= 
//   Char型の文字配列の初期化(全ての要素を Null 文字にする) 
//   Char型の静的配列の場合 
//   ZeroMemory手続きを使用する例 
//  
//   ZeroMemory手続きの引数にはバイト数が必要 
//   静的配列ならば SizeOf 関数でバイト数が取得できる 
// ============================================================================= 
procedure  TForm1.Button3Click(Sender: TObject); 
var  
  LArrChar : array  [0 ..9 ] of  Char; 
  LIndex   : Integer; 
begin  
  Memo1.Lines.Clear; 
  //  初期化確認用に要素に値をセット 
  for  LIndex := Low(LArrChar) to  High(LArrChar) do  begin  
    LArrChar[LIndex] := Char((LIndex * 2 ) + $3042 ); 
  end ; 
  Memo1.Lines.Add(LArrChar); 
  //  初期化(全て Null 文字になる) 
  ZeroMemory(@LArrChar[0 ], SizeOf(LArrChar)); 
  //  初期化後の各要素の値を確認表示 
  for  LIndex := Low(LArrChar) to  High(LArrChar) do  begin  
    Memo1.Lines.Add('$'  + IntToHex(Ord(LArrChar[LIndex]), 4 )); 
  end ; 
  Memo1.Lines.Add('SizeOf : ' + IntToStr(SizeOf(LArrChar))); 
  Memo1.Lines.Add('Length * 2 : ' + IntToStr(Length(LArrChar) * SizeOf(Char))); 
end ; 
// ============================================================================= 
//   Char型の文字配列の初期化(全ての要素を Null 文字にする) 
//   Char型の動的配列の場合 
//   FillChar手続きを使用する例 
//  
//   FillChar 手続きの第 2 引数はバイト数 
//   動的配列静的の場合,SizeOf 関数で取得した値は型のサイズになる 
// ============================================================================= 
procedure  TForm1.Button4Click(Sender: TObject); 
var  
  LArrChar : array  of  Char; 
  LText    : string ; 
  LIndex   : Integer; 
begin  
  Memo1.Lines.Clear; 
  SetLength(LArrChar, 10 ); 
  //  初期化確認用に要素に値をセット 
  for  LIndex := Low(LArrChar) to  High(LArrChar) do  begin  
    LArrChar[LIndex] := Char((LIndex * 2 ) + $3042 ); 
  end ; 
  LText := string (@LArrChar[0 ]); 
  Memo1.Lines.Add(LText); 
  //  初期化(全て Null 文字になる) 
  FillChar(LArrChar[0 ], Length(LArrChar) * SizeOf(Char), #0 ); 
  //  初期化後の各要素の値を確認表示 
  for  LIndex := Low(LArrChar) to  High(LArrChar) do  begin  
    Memo1.Lines.Add('$'  + IntToHex(Ord(LArrChar[LIndex]), 4 )); 
  end ; 
  Memo1.Lines.Add('SizeOf : ' + IntToStr(SizeOf(LArrChar))); 
  Memo1.Lines.Add('Length * 2 : ' + IntToStr(Length(LArrChar) * SizeOf(Char))); 
end ; 
// ============================================================================= 
//   Char型の文字配列の初期化(全ての要素を Null 文字にする) 
//   Char型の動的配列の場合 
//   ZeroMemory手続きを使用する例 
//  
//   ZeroMemory手続きの引数にはバイト数が必要 
//   動的配列静的の場合,SizeOf 関数で取得した値は型のサイズになる 
// ============================================================================= 
procedure  TForm1.Button5Click(Sender: TObject); 
var  
  LArrChar : array  of  Char; 
  LText    : string ; 
  LIndex   : Integer; 
begin  
  Memo1.Lines.Clear; 
  SetLength(LArrChar, 10 ); 
  //  初期化確認用に要素に値をセット 
  for  LIndex := Low(LArrChar) to  High(LArrChar) do  begin  
    LArrChar[LIndex] := Char((LIndex * 2 ) + $3042 ); 
  end ; 
  LText := string (@LArrChar[0 ]); 
  Memo1.Lines.Add(LText); 
  //  初期化(全て Null 文字になる) 
  ZeroMemory(@LArrChar[0 ], Length(LArrChar) * SizeOf(Char)); 
  //  初期化後の各要素の値を確認表示 
  for  LIndex := Low(LArrChar) to  High(LArrChar) do  begin  
    Memo1.Lines.Add('$'  + IntToHex(Ord(LArrChar[LIndex]), 4 )); 
  end ; 
  Memo1.Lines.Add('SizeOf : ' + IntToStr(SizeOf(LArrChar))); 
  Memo1.Lines.Add('Length * 2 : ' + IntToStr(Length(LArrChar) * SizeOf(Char))); 
end ; 
         
         
        
         
         
         
        
         
         
        
          
            
               レコード型の変数の初期値についても同じです. 
                  グローバルなレコード型の変数はデフォルト値で初期化されます.初期化の値は,String 型の文字列では長さ 0 の空文字で,数値では 0 です.ローカル変数のレコード型の変数は初期化されません.ただし,String 型のメンバーの値は,単独の String 型の変数と同じです.グローバル変数もローカル変数も長さ 0 の空文字で初期化されます.  
                  以下は,これらのことを確認するためのテストコードです.下のコードは,レコード型の変数がグロバール変数の場合です. 
 
             
           
        
         
        
         
        
          
            
               
              図26  
                EXE 実行開始時の画面
                 
             
            
               
              図27  
                レコード型の変数の各メンバーに値をセット 
             
           
        
         
        
copy code 
        
          unit  Unit1; 
interface  
uses  
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, StdCtrls; 
type  
  TSamleInfoRec = record  
    Text     : string ; 
    Int32    : Integer; 
    Float    : Double; 
    CharArry : array  [0 ..9 ] of  Char; 
  end ; 
  TForm1 = class (TForm) 
    Button1: TButton; 
    Memo1: TMemo; 
    procedure  FormCreate(Sender: TObject); 
    procedure  Button1Click(Sender: TObject); 
  private  
    { Private 宣言 }  
  public  
    { Public 宣言 }  
    FSampleInfo : TSamleInfoRec; 
  end ; 
var  
  Form1: TForm1; 
implementation  
{$R *.dfm}  
// ============================================================================= 
//   フォーム生成時の処理 
//   グローバルなレコード型の変数のメンバの値を表示 
// ============================================================================= 
procedure  TForm1.FormCreate(Sender: TObject); 
begin  
  Memo1.Lines.Clear; 
  Memo1.Lines.Add(FSampleInfo.Text); 
  Memo1.Lines.Add(IntToStr(FSampleInfo.Int32)); 
  Memo1.Lines.Add(FormatFloat('0.000' , FSampleInfo.Float)); 
  Memo1.Lines.Add(FSampleInfo.CharArry); 
end ; 
// ============================================================================= 
//   レコード型のメンバの値を設定 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
begin  
  Memo1.Lines.Clear; 
  FSampleInfo.Text     := '日本語 ABC 文字列' ; 
  FSampleInfo.Int32    := 5432 ; 
  FSampleInfo.Float    := 123.456 ; 
  StrPCopy(FSampleInfo.CharArry, 'Char 型文字配列' ); 
  Memo1.Lines.Add(FSampleInfo.Text); 
  Memo1.Lines.Add(IntToStr(FSampleInfo.Int32)); 
  Memo1.Lines.Add(FormatFloat('0.000' , FSampleInfo.Float)); 
  Memo1.Lines.Add(FSampleInfo.CharArry); 
end ; 
end . 
         
         
         
        
          
            
               以下のコードは,レコード型の変数がローカル変数の場合です. 
 
             
           
        
         
         
        
          
            
               
              図28  
                ローカル変数は初期化されない 
             
           
        
         
        
copy code 
        
          unit  Unit1; 
interface  
uses  
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, StdCtrls; 
type  
  TSamleInfoRec = record  
    Text     : string ; 
    Int32    : Integer; 
    Float    : Double; 
    CharArry : array  [0 ..19 ] of  Char; 
  end ; 
  TForm1 = class (TForm) 
    Memo1: TMemo; 
    procedure  FormCreate(Sender: TObject); 
  private  
    { Private 宣言 }  
  public  
    { Public 宣言 }  
  end ; 
var  
  Form1: TForm1; 
implementation  
{$R *.dfm}  
// ============================================================================= 
//   フォーム生成時の処理 
//   ローカルなレコード型の変数はは初期化されない 
//   ただし,String型の文字列はグローバルでもローカル変数でも長さ0の空文字となる 
// ============================================================================= 
procedure  TForm1.FormCreate(Sender: TObject); 
var  
  LSampleInfo : TSamleInfoRec; 
begin  
  Memo1.Lines.Clear; 
  Memo1.Lines.Add(LSampleInfo.Text); 
  Memo1.Lines.Add(IntToStr(LSampleInfo.Int32)); 
  Memo1.Lines.Add(FloatToStr(LSampleInfo.Float)); 
  Memo1.Lines.Add(FormatFloat('0.000' , LSampleInfo.Float)); 
  Memo1.Lines.Add(LSampleInfo.CharArry); 
end ; 
end . 
         
         
         
        
          
            
               レコード型の変数も,型付きの静的配列と同じように,クラスのメンバーではないグローバル変数は各メンバーの初期値を設定できます.その例です. 
 
             
           
        
         
         
        
          
            
               
              図29  
                グローバル変数は初期値を設定できる
                 
             
           
        
         
        
copy code 
        
          unit  Unit1; 
interface  
uses  
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, StdCtrls; 
type  
  TSamleInfoRec = record  
    Text  : string ; 
    Int32 : Integer; 
    Float : Double; 
  end ; 
  TForm1 = class (TForm) 
    Memo1: TMemo; 
    procedure  FormCreate(Sender: TObject); 
  private  
    { Private 宣言 }  
  public  
    { Public 宣言 }  
  end ; 
var  
  Form1: TForm1; 
implementation  
{$R *.dfm}  
var  
  FSampleInfo : TSamleInfoRec = (Text:'文字列' ; Int32:12345 ; Float:543.21 ); 
// ============================================================================= 
//   レコード型変数の初期値を設定例 
//   レコード型の変数がグローバルであれば初期値を設定できる 
// ============================================================================= 
procedure  TForm1.FormCreate(Sender: TObject); 
begin  
  Memo1.Lines.Clear; 
  FSampleInfo.Text := '日本語 '  + FSampleInfo.Text; 
  Memo1.Lines.Add(FSampleInfo.Text); 
  Memo1.Lines.Add(IntToStr(FSampleInfo.Int32)); 
  Memo1.Lines.Add(FormatFloat('0.000' , FSampleInfo.Float)); 
end ; 
end . 
         
         
         
        
          
            
               レコード型の変数も,型付きの静的配列と同じように,定数として使用する場合も,各メンバーの初期値を設定できます.その例です. 
 
             
           
        
         
         
        
          
            
               
              図30  
                定数として使用する場合は初期値を設定できる 
             
           
        
         
        
copy code 
        
          unit  Unit1; 
interface  
uses  
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, StdCtrls; 
type  
  TSamleInfoRec = record  
    Text  : string ; 
    Int32 : Integer; 
    Float : Double; 
  end ; 
  TForm1 = class (TForm) 
    Memo1: TMemo; 
    Button1: TButton; 
    procedure  Button1Click(Sender: TObject); 
  private  
    { Private 宣言 }  
  public  
    { Public 宣言 }  
  end ; 
var  
  Form1: TForm1; 
implementation  
{$R *.dfm}  
// ============================================================================= 
//   定数値としてのレコード型の変数 
//   定数値なのでメンバの値は変更できない 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
const  
  LSampleInfo : TSamleInfoRec = (Text:'文字列' ; Int32:12345 ; Float:543.21 ); 
begin  
  Memo1.Lines.Clear; 
  Memo1.Lines.Add(LSampleInfo.Text); 
  Memo1.Lines.Add(IntToStr(LSampleInfo.Int32)); 
  Memo1.Lines.Add(FormatFloat('0.000' , LSampleInfo.Float)); 
end ; 
end . 
         
         
        
         
         
         
        
         
         
        
          
            
               標準関数の Default 関数を使用すると,配列とレコード型の変数を初期化できます.ただし,配列は型宣言された変数に限ります. 
                 初期値を設定すること,つまり,配列の要素あるいはレコード型のメンバの値を特定の値にする場合も初期化ということがありますが,Default 関数による初期化は,変数のデフォルト値にすることを意味します.デフォルトの値とは,String 型では空文字,Char 型は Null 文字,数値の場合は 0 です.
                  ポインタ型とオブジェクト型の場合は nil がデフォルトの初期値です. 
                 Default 関数は,オンラインヘルプでは以下のページにしか記述がありません.おそらく,アンドキュメントな関数と言ってもいいかも知れません. 
 
             
           
        
         
        
         
        
         
         
         
        
          
            
              14_ 標準関数 Default を使用して型宣言の静的配列を初期化 
             
           
        
         
         
        
          
            
               標準関数 Default を使用して型宣言の Char 型の静的な文字配列を初期化する例です. 
                  Char 型の静的な文字配列の場合,初期化しないと,ゴミが表示されますが,Default 関数で初期化すれば全ての要素が Null 文字になります.  
                  Char 型の静的な文字配列は,使用するメモリ領域が固定です.したがって,FillChar 手続きでも初期化できます.FillChar 手続きは,型宣言なしの Char 型の静的な文字配列も初期化できます. 
 
             
           
        
         
         
        
          
            
               
              図31  
                型宣言の静的配列の初期化
                 
             
            
               
              図32  
                型宣言の静的配列の初期化
                 
             
           
        
         
        
copy code 
        
          type  
  TArrayChar = array  [0 ..4 ] of  Char; 
// ============================================================================= 
//   静的配列の初期値 (型宣言の Char 型の静的配列) 
//   初期化処理がない場合 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
var  
  LCharArry : TArrayChar; 
  LIndex    : Integer; 
begin  
  Memo1.Lines.Clear; 
  for  LIndex := 0  to  High(LCharArry) do  begin  
    Memo1.Lines.Add(IntToStr(LIndex) + ' : '  + LCharArry[LIndex]); 
  end ; 
end ; 
// ============================================================================= 
//   静的配列の初期値 (型宣言の Char 型の静的配列) 
//   Default 関数で初期化した場合 
// ============================================================================= 
procedure  TForm1.Button2Click(Sender: TObject); 
var  
  LCharArry : TArrayChar; 
  LIndex    : Integer; 
begin  
  Memo1.Lines.Clear; 
  LCharArry := System.Default (TArrayChar); 
  for  LIndex := 0  to  High(LCharArry) do  begin  
    Memo1.Lines.Add(IntToStr(LIndex) + ' : '  + LCharArry[LIndex]); 
  end ; 
end ; 
         
         
        
         
         
         
        
          
            
              15_ 標準関数 Default を使用して型宣言の動的配列を初期化 
             
           
        
         
         
        
          
            
               標準関数 Default を使用して型宣言の動的な整数型の配列を初期化する例です. 
                  このテストでは SetLength 手続きで配列の領域 (要素数) を設定しています.したがって,配列の各要素の値はデフォルトの 0 に初期化されます.  
                  動的配列を Default 関数で初期化すると,要素の値が初期化されるのではなく,配列そのものが初期化されて,要素数は 0 となります. 
 
             
           
        
         
         
        
          
            
               
              図33  
                型宣言の動的配列の初期化
                
                  初期化の処理がない場合 
                  SetLength 関数で領域 (要素数) を確保しているので 0 に初期化される 
                  
             
            
               
              図34  
                型宣言の動的配列の初期化
                
                  Default 関数で初期化した場合 
                  配列要素ではなく,配列が初期化されるので,要素の数が 0 になる 
                  
             
           
        
         
        
copy code 
        
          uses  
  System.Types; 
{$R *.dfm}  
// ============================================================================= 
//   動的配列の初期値 (型宣言の整数型の動的配列) 
//   初期化処理がない場合 
//  
//   動的配列領域 (要素数) を SetLength 手続きで割り当てた場合 
//   その領域 (要素) は 0 または nil に設定される 
//  
//   TIntegerDynArray の使用には uses に Types が必要 
// =========================================================================== 
procedure  TForm1.Button1Click(Sender: TObject); 
var  
  LArrayInt : TIntegerDynArray; 
  LIndex    : Integer; 
begin  
  Memo1.Lines.Clear; 
  SetLength(LArrayInt, 4 ); 
  for  LIndex := 0  to  High(LArrayInt) do  begin  
    Memo1.Lines.Add(IntToStr(LIndex) + ' : '  + IntToStr(LArrayInt[LIndex])); 
  end ; 
end ; 
// ============================================================================= 
//   動的配列の初期値 (型宣言の整数型の動的配列) 
//   Default 関数で初期化した場合 
//   領域 (要素数) は 0 となる 
//  
//   TIntegerDynArray の使用には uses に Types が必要 
// ============================================================================= 
procedure  TForm1.Button2Click(Sender: TObject); 
var  
  LArrayInt : TIntegerDynArray; 
begin  
  Memo1.Lines.Clear; 
  SetLength(LArrayInt, 4 ); 
  LArrayInt := System.Default (TIntegerDynArray); 
  Memo1.Lines.Add('要素数 : '  + IntToStr(Length(LArrayInt))); 
end ; 
         
         
        
         
         
         
        
          
            
              16_ 標準関数 Default を使用してレコード型を初期化 
             
           
        
         
         
        
          
            
               標準関数 Default を使用してレコード型を初期化する例です.レコード型の初期化は,レコード型の各メンバの値をデフォルトの初期値に設定することを意味します. 
                  初期化しない場合はかなり文字化けしていますが,この状態はその時のメモリの状態にもよります.下図は IDE 上で実行した結果ですが,この程度の単純なプログラムであれば,EXE を直接実行すれば文字化けはほとんど発生しません. 
                 String 型の変数は,グローバルな変数であっても,ローカルな変数でも,レコード型のメンバであっても空文字に初期化されます. 
                   
                  レコード型の変数の初期化に FillChar 手続きも使用できますが,レコードのメンバに String 型等,可変長の変数があると問題が発生します.  
                  FillChar 手続きは,指定バイト数のメモリの値を特定の値 にする関数です.  
                  PChar 型も任意の文字数を格納できますが,PChar はポインタ型です.ポインタ型の変数が示すアドレスは,32 ビットのアプリでは 4 バイト,64 ビットのアプリでは 8 バイトの固定長です. 
 
             
           
        
         
         
        
          
            
               
              図35  
                レコード型の初期化
                
                  初期化の処理がない場合 
                  結果はその時のメモリの状態による 
                  
             
            
               
              図36  
                レコード型の初期化
                 
             
            
               
              図37  
                再び [Button1] をクリックした結果
                
                  初期化の操作によってメモリの状態が変化している 
                  結果はその時のメモリの状態による 
                  
             
           
        
         
        
copy code 
        
          type  
  TSamleInfoRec = record  
    Text     : string ; 
    Int32    : Integer; 
    Float    : Double; 
    CharArry : array  [0 ..9 ] of  Char; 
  end ; 
// ============================================================================= 
//   レコード型の初期値 
//   String 型はグローバルでもローカルでも空文字に初期化される 
// ============================================================================= 
procedure  TForm1.Button1Click(Sender: TObject); 
var  
  LSampleInfo : TSamleInfoRec; 
begin  
  Memo1.Lines.Clear; 
  Memo1.Lines.Add('Text     : '  + LSampleInfo.Text); 
  Memo1.Lines.Add('Int32    : '  + IntToStr(LSampleInfo.Int32)); 
  Memo1.Lines.Add('Float    : '  + FloatToStr(LSampleInfo.Float)); 
  Memo1.Lines.Add('Float    : '  + FormatFloat('0.000' , LSampleInfo.Float)); 
  Memo1.Lines.Add('CharArry : '  + LSampleInfo.CharArry); 
end ; 
// ============================================================================= 
//   レコード型の初期化 
//   Default 関数で初期化した場合 
// ============================================================================= 
procedure  TForm1.Button2Click(Sender: TObject); 
var  
  LSampleInfo : TSamleInfoRec; 
begin  
  Memo1.Lines.Clear; 
  LSampleInfo := System.Default (TSamleInfoRec); 
  Memo1.Lines.Add('Text     : '  + LSampleInfo.Text); 
  Memo1.Lines.Add('Int32    : '  + IntToStr(LSampleInfo.Int32)); 
  Memo1.Lines.Add('Float    : '  + FloatToStr(LSampleInfo.Float)); 
  Memo1.Lines.Add('Float    : '  + FormatFloat('0.000' , LSampleInfo.Float)); 
  Memo1.Lines.Add('CharArry : '  + LSampleInfo.CharArry); 
end ;