【MQL4の勉強】変数のスコープ(有効範囲)とは?プログラム書き方やサンプルあり!

ザフナーラボブログ

MQL4でプログラミングを行う際に使用する変数は、以下の種類に応じて、プログラムの中の決められた範囲でのみ有効(=変数に格納された値が記憶される。)となります。

  • ローカル変数
  • グローバル変数
  • 静的ローカル変数
  • 大域変数

1.ローカル変数

ローカル変数とは、関数の中で宣言された変数をいいます。

例えば、以下のようなスクリプトを作成したとします(スクリプトの作成方法については「こちら」を参照してください。)。

サンプルコード


#property strict

#property show_confirm

//関数の定義
void Count()
{
int Count_Number = 0;

Count_Number++;

Print("Count_Number is ",Count_Number);
}

void OnStart()
{
Count();
Count();
Count();
}

上記のスクリプトを実行すると、「ターミナルウィンドウ」の「エキスパート」タブに、以下のような表示がなされます。

サンプルコード


Count_Number is 1
Count_Number is 1
Count_Number is 1

これは、以下のような処理が実行されたことを意味します。

  • Count()関数の実行(1回目)
    関数内で宣言した変数「Count_Number」の値を「0」で初期化

    変数「Count_Number」の値に「1」を加える。

    Print()関数(詳細は「こちら」を参照してください。)を実行
  • Count()関数の実行(2回目)
    関数内で宣言した変数「Count_Number」の値を「0」で初期化

    以下、1回目と同様
  • Count()関数の実行(3回目)
    関数内で宣言した変数「Count_Number」の値を「0」で初期化

    以下、1回目と同様

つまり、変数を関数の中で宣言した場合には、当該変数に格納された値の記憶は、当該変数を宣言した関数内でのみ存続する、ということになります。

換言すれば、ローカル変数の場合は、当該変数を宣言した関数の実行が終了すると、その関数内で記憶した値は、他の処理において引き継がれない、ということになります。

2.グローバル変数

グローバル変数とは、関数の外で宣言された変数をいいます。

例えば、以下のようなスクリプトを作成したとします(スクリプトの作成方法については「こちら」を参照してください。)。

サンプルコード

#property strict

#property show_confirm

//変数の宣言
int Count_Number = 0;

//関数の定義
void Count()
{
  Count_Number++;
  
  Print("Count_Number is ",Count_Number);
}

void OnStart()
{
  Count();
  Count();
  Count();
  
  Print("Count_Number is ",Count_Number);
}

上記のスクリプトを実行すると、「ターミナルウィンドウ」の「エキスパート」タブに、以下のような表示がなされます。

サンプルコード


Count_Number is 3
Count_Number is 3
Count_Number is 2
Count_Number is 1

これは、以下のような処理が実行されたことを意味します。

  • 変数の初期化
    変数「Count_Number」が生成され、「0」で初期化
  • Count()関数の実行(1回目)
    変数「Count_Number」の値に「1」を加える。
    (=変数「Count_Number」の値は「1」)

    Print()関数(詳細は「こちら」を参照してください。)を実行
  • Count()関数の実行(2回目)
    変数「Count_Number」の値に「1」を加える。
    (=変数「Count_Number」の値は「2」)

    Print()関数を実行
  • Count()関数の実行(3回目)
    変数「Count_Number」の値に「1」を加える。
    (=変数「Count_Number」の値は「3」)

    Print()関数を実行
  • Print()関数を実行
    変数「Count_Number」の値は「3」

つまり、変数を関数の外で宣言した場合には、当該変数に格納された値の記憶は、当該変数を宣言した関数を超えて存続する、ということになります。

換言すれば、グローバル変数の場合は、当該変数を宣言した関数の実行が終了しても、その関数内で記憶した値は、他の処理においても引き継がれる、ということになります。

3.静的ローカル変数

静的ローカル変数とは、「static」を付けて、関数の中で宣言された変数をいいます。

例えば、以下のようなスクリプトを作成したとします(スクリプトの作成方法については「こちら」を参照してください。)。

サンプルコード



#property strict

#property show_confirm

//関数の定義
void Count()
{
  static int Count_Number = 0;
  
  Count_Number++;
  
  Print("Count_Number is ",Count_Number);
}

void OnStart()
{
  int Count_Number = 0;
  
  Count();
  Count();
  Count();
  
  Print("Count_Number is ",Count_Number);
}

上記のスクリプトを実行すると、「ターミナルウィンドウ」の「エキスパート」タブに、以下のような表示がなされます。

サンプルコード


Count_Number is 0
Count_Number is 3
Count_Number is 2
Count_Number is 1

これは、以下のような処理が実行されたことを意味します。

  • 変数の初期化
    変数「Count_Number」が生成され(OnStart()関数内)、「0」で初期化
  • Count()関数の実行(1回目)
    変数「Count_Number」が生成され(Count()関数内)、「0」で初期化

    Count()関数内で生成された変数「Count_Number」に「1」を加える。
    (=Count()関数内で生成された変数「Count_Number」の値は「1」)

    Print()関数(詳細は「こちら」を参照してください。)を実行
  • Count()関数の実行(2回目)
    Count()関数内で生成された変数「Count_Number」に「1」を加える。
    (=Count()関数内で生成された変数「Count_Number」の値は「2」)

    Print()関数を実行
  • Count()関数の実行(3回目)
    Count()関数内で生成された変数「Count_Number」に「1」を加える。
    (=Count()関数内で生成された変数「Count_Number」の値は「3」)

    Print()関数を実行
  • Print()関数を実行
    OnStart()関数内で生成された変数「Count_Number」の値(=「0」)を出力

つまり、変数を関数の中で「static」を付けて宣言した場合には、当該変数に格納された値の記憶は、当該変数を宣言した関数を超えて存続する、ということになります。

換言すれば、静的ローカル変数の場合は、当該変数を宣言した関数の実行が終了しても、その関数内で記憶した値は、他の処理においても引き継がれる、ということになります。

なお、グローバル変数と静的ローカル変数の変数の違いは、以下の点にあります。

  • グローバル変数の場合は、その値が、全ての関数において共有されます。
    したがって、2.で掲げた例のように、Count()関数・Print()関数のいずれにおいても、以前の値に「1」を加えた値が出力されるという処理がなされています。
  • 静的ローカル変数の場合は、あくまでも、当該変数を宣言した関数を使用する限りにおいて、以前の値を記憶します。
    したがって、上記の例のように、Count()関数においてのみ、以前の値に「1」を加えた値が出力されるという処理がなされています。
    つまり、OnStart()関数内で宣言された変数「Count_Number」と、Count()関数内で宣言された変数「Count_Number」とは、名称は同じですが、異なるものとして扱われていることになります。

4.大域変数

グローバル変数及び静的ローカル変数は、以前に格納された値を記憶して、それに基づいて一定の処理を行わせるために使用しますが、EAやインジケーターをチャートから削除したり、MetaTrader4(MT4)自体を終了した場合には、それらの変数に記憶された情報は失われてしまいます。

したがって、その後に改めて、EAやインジケーターをチャートに適用したり、MT4を起動した場合には、再度、変数に係る設定を行う必要があります。

しかし、以前に格納されていた値をMT4自体に記憶させておくように変数を設定しておけば、そのような作業を行う必要はなくなります。

このように、MT4自体に以前に格納されていた値を記憶させている変数を、大域変数といいます。

大域変数を設定するためには、以下のように記述します。

サンプルコード


int OnInit()
{
  変数 = GlobalVariableGet("変数名");
  
  return(INIT_SUCEEDED);
}

void OnDeinit(const int reason)
{
  GlobalVariableSet("変数名",変数);
}