今回から補足知識を説明していきます。
補足記事
この基礎編パート1では、プログラミングに必要な最低限の知識を習得してきました。
ただ、他の人が書いたスケッチを見てみると、今までの説明に出てこなかったコードで書かれている場合があります。
それらすべてを隅々まで理解するには、さらに多くの知識が必要になります。
そこで、Arduinoのスケッチでよく見かけるコードについて、何回かの記事に分けて補足解説します。
#defineによる定数定義(復習)
第15回の記事で、スケッチの中に出てくる定数を#define
を使って定義する方法を解説しました。
例えば、10番端子に接続している緑色LEDを出力制御に設定して点灯する場合、#define
を使わないで書くと次のようなスケッチになります。
pinMode(10, OUTPUT); // 10番端子を出力制御にする
digitalWrite(10, HIGH); // 10番端子の内部スイッチをONにする
でもこのようなコードを書いてしまうと、LEDの接続端子を変更した場合、端子番号の「10」を何ヵ所も変更する手間がかかってしまいますし、間違える可能性もありますよね。
そこで、次のようにLEDを接続している端子番号を#define
で定義すると、変更しやすくなりますし、スケッチも読みやすくなる、というメリットがありました。
#define GREEN_LED 10 // 緑色LEDの接続端子番号を定義
pinMode(GREEN_LED, OUTPUT); // 緑色LEDの接続端子を出力制御にする
digitalWrite(GREEN_LED, HIGH); // 緑色LEDをONにする
上のスケッチではコメントを書いていますが、コメントがなくても何をしているのかなんとなく想像つきますよね。
ところで、このように定数を定義する方法は他にもあります。
そこで、Arduinoのサンプルスケッチなどでよく見かける次の2通りの定数数定義の方法をご紹介します。
- constによる定数定義
- 変数による定数定義
なんのこっちゃ?って感じですので、それぞれ詳しく見ていきましょう!
❶ constによる定数定義
変数宣言?
Arduinoのサンプルスケッチを見ると、定数定義として次のような書き方がされているケースがあります。
const int GREEN_LED = 10; // 緑色LEDの接続端子番号を定義
pinMode(GREEN_LED, OUTPUT); // 緑色LEDの接続端子を出力制御にする
digitalWrite(GREEN_LED, HIGH); // 緑色LEDをONにする
1行目は変数宣言のように見えますが、変数宣言の前にconst
と書かれていて、意味がよくわからないですよね。
でもこのスケッチは先ほどの緑色LED制御のスケッチと同じ意味になっているんです!
先ほどのスケッチでは#define GREEN_LED 10
と書いて、GREEN_LED
は10の意味としていました。このスケッチも同様にGREEN_LED
は10の意味として解釈されます。
でもこのスケッチは1行目が謎ですよね。そこで、このスケッチの意味を理解していきましょう。
最初に、1行目のconstがないスケッチを考えてみます。
int GREEN_LED = 10; // 緑色LEDの接続端子番号を定義
pinMode(GREEN_LED, OUTPUT); // 緑色LEDの接続端子を出力制御にする
digitalWrite(GREEN_LED, HIGH); // 緑色LEDをONにする
このスケッチの1行目では、int
型のGREEN_LED
という変数を宣言して10で初期化しています(10を代入しています)。
3行目と4行目では、このGREEN_LED
を引数の端子名に使用しています。GREEN_LED
は10が代入されていますので、pinMode
とdigitalWrite
の端子名に「10」が指定されるわけです。
でもこの書き方の場合、GREEN_LED
は変数ですが、この変数を変更することはありませんよね。#define GREEN_LED 10
と同様に、GREEN_LED
に何かを代入して変更することはありません。
でも実際にはint GREEN_LED = 10;
と書いているわけですから、どこからどう見てもGREEN_LED
は変数です。
初めてこのスケッチを見た人はGREEN_LED
は変数だからどこかで変更することがあるのかな?などと思ってしまいます。
そこで、このように変数として宣言した場合でも、この変数は定数でスケッチの中では変更することはありませんよ、という書き方があります。
それがconstです。
const int GREEN_LED = 10;
このように、変数宣言の前にconst
と書くと、GREEN_LED
は変数ではなく定数として扱ってください、という意味になります。
例えばconst付きで宣言した変数を、次のように変更しようとするとエラーになります。
const int GREEN_LED = 10; // 定数
GREEN_LED = 8; // 定数を変更しようとしているのでエラーになる!
Arduinoのサンプルスケッチや、他の人が書いたコードなどをみると、#define
ではなくこのようにconst
を使用しているケースもありますので、ぜひ頭の片隅に入れておいていただければと思います。
なお、上の例では#defineと同様に定数名を大文字のGREEN_LED
としましたが、変数と同様に次ように小文字で書く場合も多く見られます。(個人的な印象としては小文字で書くケースが多いように思います)
const int green_led = 10; // 緑色LEDの接続端子番号を定義
pinMode(green_led, OUTPUT); // 緑色LEDの接続端子を出力制御にする
digitalWrite(green_led, HIGH); // 緑色LEDをONにする
constを使うメリット
結局、const
は#define
と同様の働きをするため、#define
との違いがよくわかりませんよね。
constと#defineの大きな違いは「constの場合、データの型がわかる」という点があります。
例えば、タイマーの時間を整数で定義するためにTIMER_TIME
という名前で定義したい場合、constと#defineは次のようになります。
const int TIMER_TIME = 10; // constを使った定数の場合
#define TIMER_TIME 10 // #defineを使った定数の場合
この2つの書き方の大きな違いは、const
ではTIMER_TIME
が整数であることが明確、という点です。
#define
はTIMER_TIME
はどのようなデータ型なのかよくわかりません。例えば次のように小数を定義することもできてしまいます。
#define GREEN_LED 10.5
const
の場合は、TIMER_TIME
はint
型で宣言されているので、次のように定義するのはおかしい、と気づきますよね。
const int GREEN_LED = 10.5; // int型変数なので、この行だけでおかしいことがわかる
このように、定数を定義するときにデータ型が明確になっているconst
が使われることがよくあります。
スケッチ例などでconst
を見かけた場合、このように背景があるんだな、と思っていただければと思います。
❷ 変数による定数定義
ここまで、定数を定義するために#defineとconstの2種類をご紹介してきました。
でもArduino IDEのサンプルスケッチをみると、定数を変数として宣言しているケースもあります。
ちょっと???ですよね。
そこで、具体的なサンプルスケッチで確認してみます。
Arduino IDEのメニューから「ファイル」▶︎「スケッチ例」▶︎「01.Basics」▶︎「DigitalReadSerial」という名前のスケッチがあります。スケッチは次のようになっています。
/*
DigitalReadSerial
Reads a digital input on pin 2, prints the result to the Serial Monitor
This example code is in the public domain.
https://www.arduino.cc/en/Tutorial/BuiltInExamples/DigitalReadSerial
*/
// digital pin 2 has a pushbutton attached to it. Give it a name:
int pushButton = 2;
// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
// make the pushbutton's pin an input:
pinMode(pushButton, INPUT);
}
// the loop routine runs over and over again forever:
void loop() {
// read the input pin:
int buttonState = digitalRead(pushButton);
// print out the state of the button:
Serial.println(buttonState);
delay(1); // delay in between reads for stability
}
このスケッチの制御内容は、スイッチが接続されている端子の状態をdigitalRead
で読み取って(25行目)、その結果をシリアルモニタに表示する(27行目)、という内容です。
このスケッチでは、スイッチの接続端子を12行目で定義しています。次のように、pushButtonという変数を宣言して2で初期化しています。
int pushButton = 2;
この行はconstが付いていないので変数になってしまっています。でも実際には接続端子の定義としていますので、スケッチの中ではpushButton
は変更することはありません。
このようにスケッチによっては、定数を変数として宣言するケースも見られます。
ただ、このようなケースの場合、Arduino IDEは賢く振舞います。
Arduino IDEは、12行目でpushButton
という変数が宣言されているものの、スケッチの中ではpushButton
は変更されいないので定数として認識します。
本来でしたらint
型のpushButton
はグローバル変数として宣言していますので、メモリにpushButton
の保存領域が確保されメモリが消費されてしまいます。
でもArduino IDEは、pushButton
は変数として用意する必要がないので、メモリには保存領域を用意しない、という処理をします。
定数定義まとめ
Arduinoのスケッチで定数を定義する場合、次の3種類があります。サンプルスケッチを読むときなど注意していただければと思います。
#define
による定義const
による定義- 変数による定義
更新履歴
日付 | 内容 |
---|---|
2019.12.28 | 新規投稿 |
2021.8.27 | 新サイトデザイン対応 |
2025.1.15 | 説明内容を#defineとconstに変更 |