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("変数名",変数);
}
- GlobalVariableGet()関数の詳細については「こちら」を参照してください。
- GlobalVariableSet()関数の詳細については「こちら」を参照してください。