第27回 変数の詳細1 〜変数のスコープ〜

今回は変数について理解を深めます。

今回の説明内容

今回の記事では、変数について理解を深めていきます。

前回までの記事で、変数はこういうもので、スケッチではこのように書きます、と説明してきました。でも自分で変数使ってプログラミングするとなると、なんとなくまだフワフワした感じがあるのではないでしょうか。

そこで、今回は変数の性質について理解を深めます。ちょっと難しいところもあるかもしれませんが、じっくり読み進めれば大丈夫です!

 

複数の変数の宣言

今のところ使用している変数は時間を計測するための「count」という名前のもの1つだけです。

スケッチが複雑になってくると、使用する変数も増えてきます。複数の変数を使用する場合、例えば「a」「b」「c」という名前の3つの変数を使用する場合、もちろん以下のように一つずつ宣言しても全く問題ありませんが、

uint8_t a;
uint8_t b;
uint8_t c;

以下のように「,」(カンマ)で区切って宣言することもできます。

uint8_t a, b, c;

今後のスケッチでは適宜どちらかの書き方にします。

 

初期化

while文を使用した時間計測のスケッチでは、最初に計測に使用する変数を以下のように宣言しました。

uint8_t count;

変数を宣言した場合、用意された変数は適当な数字になっていますので、以下のように値を代入しました。

count = 1;

このように宣言をしたあと、値を代入する、というケースは多いので、変数を宣言するときに値を代入しておくことができるようになっています。

uint8_t count = 1;

このように宣言すると、1が代入されているcountという名前の変数を用意してくれます。

このように最初に値を設定しておくことを「変数の初期化」と呼んでいます。

変数の書き方についてはこれまで説明した内容で十分です。書き方はこれでいいとしても、ちょっと疑問が残ってるんですよね。

 

ちょっとした疑問

キッチンタイマーのスケッチでは、変数を利用して時間を計測することができるようになりました。変数の扱いはある程度わかったものの、ちょっと疑問が残ります。

その疑問とは、変数の宣言の位置です。特に詳しい説明もなく、時間を計測するための変数として「count」という名前の変数を以下の位置で宣言しました。

loop内の変数宣言

変数の宣言というのは、Arduinoボード本体に「〇〇という型の□□という名前の変数を用意してください」と依頼するものでしたよね。変数を用意してもらうように依頼するだけですので、変数の宣言は上の位置以外ではダメなのでしょうか。例えば、以下のように変数を宣言するとどうなるのでしょうか。

loop外の変数宣言

今回の記事では、このちょっとした疑問から出発して、変数の性質について理解を深めていきます。

 

変数を宣言する場所のルール

変数を宣言する場所のルールは、大きく2つあります。

ひとつは「変数を使う前に宣言する」というルールです。以下のように変数を宣言する前に変数を使うと、例のごとく「そんな変数は知らない!」と英語で怒られます。

変数宣言エラー

宣言する前に使ったとは言っても、もうちょっと後の方で宣言してるのに、、、って気もしますよね。でもArduino IDEはスケッチを解釈するとき、最初の行から順番に1行1行みていきます。たとえ次の行に変数宣言があったとしても、変数を宣言する前に使用すると怒られます。

ところで、変数の宣言は変数を使用する前であれば大丈夫なのはいいとして、前と言ってもそれなりに範囲がありますよね。

変数の宣言範囲

変数を宣言する位置は、使用する前であればどこでもいい、というわけではありません。

ここでもうひとつ、とても重要なルールの登場です。

その重要なルールとは「宣言した変数は『{』と『}』で囲まれた内部のみで有効」というものです。ちょっとわかりづらいですので実際のスケッチを見ながら確認していきます。

キッチンタイマーで時間を計測するときに使用した変数「count」は、以下の位置で宣言しました。

変数countの宣言位置

この変数は、loopの「 { 」と「 } 」で囲まれた内部で宣言しています。変数countは宣言したあと、「 { 」と「 } 」の内部のみ有効ですので、「count」が使えるのは以下の範囲内です。

変数countの使用可能範囲

ところでこのスケッチをよくみると、for文のところに「 { 」と「 } 」がありますよね。この内部ではどうなるのでしょうか。

複数の{と}

このように「 { 」と「 } 」の内部に「 { 」と「 } 」がある場合、その内部の「 { 」と「 } 」で囲まれた部分でも使うことができます。

このように、変数を宣言すると、宣言した階層より下の階層の「 { 」と「 } 」で囲まれた部分でも使用することができます(階層が何重になっていても、変数宣言したところより内部であれば使用できます)。ということは、以下の場所で「count」を宣言した場合はどうなるのでしょうか。

グローバル変数宣言

「count」は、setupとloopの「 { 」と「 } 」の1階層上で宣言していますよね。

グローバル変数宣言位置

先ほどのルールでは、変数を宣言した階層より下の階層にある「 { 」と「 } 」の内部でも使用することができる、と説明しました。つまり、上のように「count」を宣言すると、宣言した行以降のところで(setupとloopのどちらの「 { 」と「 } 」の内部でも)使用することができるようになります。

グローバル変数使用可能範囲

このように、変数は宣言した位置で使用できる範囲が決まります。この使用できる範囲のことを意識高い系の言葉では「スコープ」と呼んでいます。「スコープ」は日本語では「範囲」という意味なので、「変数の有効範囲」とか言えばいいような気もしますが「変数のスコープ」と呼びます。

「スケッチのそこで変数を宣言したら、この場所はその変数が使える範囲じゃないよ」というのではなく「スケッチのそこで変数を宣言したら、ここはその変数のスコープ外だよ」というような言い方をします。

 

ローカル変数とグローバル変数

変数には使える範囲(スコープ)のルールがあることがわかりました。ここでさらに変数を使用できる範囲の観点から変数の種類を分類する言葉がありますので覚えることにしましょう。

最後の例のように、どこの「 { 」と「 } 」の内部にもないところで変数を宣言すると、その宣言した行以降から最後の行までの範囲で使うことができます。

グローバル変数

このように宣言した変数はスケッチの広範囲で使用できるため「グローバル変数」と呼んでいます。「グローバル」は日本語で「全体的な」というような意味です。

一方で、タイマーの時間計測で使用した変数のように、特定の「 { 」と「 } 」の中で宣言した変数は、その内部のみで使用できます。

ローカル変数

このように部分的に使用できる変数を「ローカル変数」と呼んでいます。「ローカル」は日本語で「局所的な」というような意味です。

ところで、変数にはスコープがあり、宣言する場所によってグローバル変数とローカル変数があることはわかったのですが、またちょっと疑問が出てきてしまいました。

例えば、タイマー時間を計測するために「count」という名前の変数を宣言する場合、グローバル変数で宣言しても、ローカル変数で宣言しても、どちらも問題なく動作します。

では、変数の宣言はどこで行うべきなのでしょうか???

グローバル変数で宣言すればどこでも使えるので、全部グローバル変数で宣言してしまった方が安心のような気がしませんか?

そこで次回の記事で、Arduinoボード本体がグローバル変数やローカル変数をどのように扱っているのか、Arduinoボード内部で何が起こっているのか解明して、変数はどのように宣言するのが適切なのか解明していきます。

 

 

更新履歴

日付 内容
2019.9.11 新規投稿