※どの記事も、文章中に出てくる各用語については、なるべく関連記事のリンクを貼るようにしているので、講座記事を読み進めていく中で、「わからなくなってしまった」、「忘れてしまった」言葉が出てきたら、クリックして復習していただければと思います<m(__)m>
改めて前回の内容をおさらいをしておくと、
- 関数とは特定の仕事をこなす、コードの固まりである。
ということをお伝えしました。
今回はローカル変数 というものについて解説していきたいと思います<m(__)m>
変数の基本概念については↓の
についてお伝えしたのですが、今回はその変数についてもう一段踏み込んで解説していきます。
今回の記事、及び次回のMQL5 EA講座 第27回「グローバル変数について」についてを読んで勉強する事によって、変数についての理解はほぼ完璧になるのではないかと思います。
是非今回も楽しみながらお読みいただければと思います。
変数の有効範囲(スコープ)について
ローカル変数とは何か?
をお話しする前に、変数の有効範囲(スコープ)について一度解説をしておきたいと思います。
関数というのは以下のような構造になっています。↓
関数名(引数記述箇所)
{
具体的な処理内容を書く箇所
}
自動売買プログラム(EA)を作るにあたって、一番お世話になるであろうOnTick関数を例に、見てみると
void OnTick()
{
}
↑がOnTick関数の基本的な形です。
これを最初のたたき台にして、私たちはEA開発プログラミングの記述をしていくわけですが、ここで私たちは
2つの選択を迫られます。すなわち、
プログラムの記述をOnTick関数の中に書くか?、外に書くか?
という選択です。
関数の外の部分をグローバル領域といいます。
//ここはグローバル領域
void OnTick()
{
//ここは関数の中
}
関数の中で宣言した変数と、関数の外(=グローバル領域)で宣言した変数では有効範囲が変わってきます。
ローカル変数とは?
ここまでの、前提を踏まえた上で改めて言うと、
といいます。
//↓これはグローバル変数
int varGlobal;
void OnTick()
{
//↓これはローカル変数
int varLocal;
}
↑こんな感じですね。
今回はローカル変数についてです。
ローカル変数の有効範囲 その1
端的に言えば、
ローカル変数の有効範囲は
宣言をした関数の中
に限定されます。
これだけの説明だとよくわからないと思いますので、コードで見てみましょう。
//intの戻り値の、sampleFunctionという名前の関数を宣言
int sampleFunction()
{
//int型の変数「varInt」を宣言
int varInt;
//変数「varInt」の値を戻り値として返す
return varInt;
}
void OnTick()
{
//変数「varInt」に5を代入
varInt=5;
}
//varIntはsampleFunction関数のローカル変数なのでコンパイルエラーになる。
sampleFunction関数の中で、整数型の変数「varInt」を宣言しました。
変数「varInt」は、sampleFunction関数の中で宣言した変数なので、sampleFunction関数の中でだけ有効なローカル変数です。
そのためOnTick関数内で変数「varInt」使おうとするとコンパイルエラーになってしまいます。
実際にコンパイルすると・・・
予想通りコンパイルエラーが発生しています。
エラー内容は、
というもので、OnTick関数で、sampleFunction関数のローカル変数を使おうとしたことで発生したエラーです。
//intの戻り値の、sampleFunctionという名前の関数を宣言
int sampleFunction()
{
//int型の変数「varInt」を宣言
int varInt;
//変数「varInt」の値を戻り値として返す
return varInt;
}
void OnTick()
{
//変数「varInt」を宣言し、5を代入
int varInt=5;
}
//OnTick内で宣言をしたのでエラーは解消された
↑のサンプルコードでは、OnTick関数の中に書いていた変数「varIn」tの前に、整数型を表す intを記述しました。
これでOnTick関数内にローカル変数「varInt」が作られたので、コンパイルエラーは解消されました。
同じ名前の変数名について
上のサンプルコードにおいては、OnTick関数とsampleFunction関数内に全く同じ名前の「varInt」が存在している状態ですが、
どちらもその関数内限定のローカル変数ですから、文法的には問題ありません。
ですが、特別な意図がある場合を除いて、同じ変数を使うことは無用の混乱を招くので望ましいことではありません。
変数名は重複しない(=ユニーク)ものをつけるよう心がけましょう。
※同じ関数の{}内に、同じ変数名をつけると当然コンパイルエラーが発生します。
void sampleFunction()
{
int varInt=5;
int varInt=10;
}
実行すると
エラーの意味は「varIntはすでに定義済みの変数です。前のvarInt変数宣言を確認してください」
です。
ローカル変数の有効範囲 その2
ここまで、
という話をしてきました。
ここからは、
について解説していきたいと思います。
「何を言っているの?( ゚Д゚)」
と思われるかもしれませんが、大した話ではないので構えずに聞いてください。
順を追って説明していきます。
先ほど
と書きましたが、
もっと厳密に書くと、ローカル変数の有効範囲は
宣言した { } の中
に限定されます。
関数も、具体的な記述は
{ }の中に記述しますよね?
ローカル変数を宣言した関数以外に、{ }を使った記述がない場合は特に問題がないのですが、↓
//intの戻り値の、sampleFunctionという名前の関数を宣言
int sampleFunction()
{
//int型の変数「varInt」を宣言
int varInt;
//変数「varInt」の値を戻り値として返す
return varInt;
}
//変数「varInt」はsampleFunction関数のローカル変数である。
{ }を使った記述が複数ある場合は注意が必要です。↓
//void型の、sampleFunctionという名前の関数を宣言
void sampleFunction()
{
//bool型の変数「barBool」を宣言しをtrueを代入
bool barBool=true;
if(barBool==true)
{
double varDouble=0.5;
}
Print(varDouble);
}
//「undeclared identifier」コンパイルエラーが発生する
上記のコードでは、sampleFunction関数の中に
が入っています。
if文についてはまだ詳しく説明していないのですが、
if(ここに書かれている条件を満たしていたら){この中に書かれている記述を実行する}
という構造を持つ文のことです。(講座記事第34回「if文について」で詳細を解説予定です↓)
if文も{}を使う構造、ということがお分かりいただけるかと思います。
従って、if文中の{}で宣言されたdouble型の変数「varDouble」はif文中の{}でのみ有効です。
にもかかわらず、if文の{}の外である領域でPrint関数の引数に「varDouble」を使おうとしています。
これは「varDouble」の有効範囲外なのでコンパイルエラーが発生してしまいます。
やってみましょう。↓
予想通り、コンパイルエラーが発生しました。
ローカル変数と、その有効範囲に関する考え方の基本は以上の通りになります。
冒頭にお伝えしたように、次回はグローバル変数について解説予定です。<m(__)m>
グローバル変数とローカル変数を合わせて理解することで、有効範囲(スコープ)の理解もより深まりますので、是非楽しみにしていてください。
※サンプルコードの中の、voidや この項の文中で使った 引数 という概念については大丈夫でしょうか?
「あれ?なんだったっけ?」という方は前回の「関数について」をご覧ください。↓
おまけ
ここからはオマケです。
MQL4 は昔のbuild(=ヴァージョン) だと関数内で宣言されたローカル変数は、たとえ宣言箇所がブロック内だとしても、関数内全体で有効性を保っていました。
/void型の、sampleFunctionという名前の関数を宣言
void sampleFunction()
{
//bool型の変数「barBool」を宣言しをtrueを代入
bool barBool=true;
if(barBool==true)
{
double varDouble=0.5;
}
Print(varDouble);
}
//MQL4の昔のバージョンならコンパイルエラーにならなかった。
今だとMQL4、MQL5ともに
Print(varDouble);
のところでコンパイルエラーになりますが、昔のMQL4のヴァージョンだと有効でした。
更新をやめたブログのソースコード等に、その名残りが伺える時がありますね。
まとめ
今回はローカル変数 について解説しました。
今回の記事では以下のことを学びました
- 関数の外の部分をグローバル領域という。
- より厳密に定義すると、ローカル変数の有効範囲は宣言した { }の中に限定される。
ローカル変数と次回解説のグローバル変数の違いを理解することは重要です。
グローバル変数はプログラム全体でアクセス可能であり、そのため、プログラムの異なる部分間でのデータの共有に適しています。
一方で、ローカル変数は関数やブロック内でのみ有効であり、プログラムの特定の部分にデータを限定するのに適しています。
ローカル変数を適切に使用することで、プログラムはより構造化され、エラーの可能性が減少します。ローカル変数とグローバル変数の適切な使い分けと、それぞれのスコープの理解は、効率的で読みやすいコードを書くための重要なスキルとなります。
今回は以上になります。
最後までお読みいただきありがとうございました<m(__)m>
コメント