\ AmazonにてArduino UNO R4 発売中!! /

Arduino 入門 番外編 15 【#define】と【const】

arduino-extra-edition-15-00 Arduino番外編
記事に広告(アフィリエイト広告)が含まれています。
スポンサーリンク

Arduino 入門
番外編 15
【#define】と【const】

こんにちは管理人のomoroyaです。

arduino 入門 番外編はarduinoの基本的なことを解説している記事です。

 

本記事は、管理人も使い分けをきちんと理解していない【#define】と【const】について改めて考えてみます。

なぜ、改めて考えるかというとスケッチ(コード)で定数の定義の仕方が本やネットのサンプルスケッチ(コード)によってマチマチだからです。

 

管理人はプログラマーの専門家というわけではありません。

これまでは、#defineとconstをあまり意識していませんでした。

そこで今回改めて考えることにしました。

 

変数のスコープとも絡むお話となります。

下記の記事を読んでおくとより理解が深まると考えます。

 

arduino自身のこと、スケッチ(コード、プログラム)を少しづつ理解して行きましょう。

いやいや、arduinoを早速始めたいんだ!というかたは下記の入門編からお読みください。

 

Arduino入門編の解説にて使用しているArduinoは互換品です。

互換品とは言え、Arduinoはオープンソースであり複製して販売するのもライセンス的に問題なし。

そのため互換品の品質も悪くなく、それでいて値段は安いです。

正規品本体の値段程度で豊富な部品が多数ついています。

 

正規品の本体単品がほしい方はこちらとなります。

 

スポンサーリンク

定数の定義でよく見かける構文

スケッチ(コード)の中には定数の定義が必ずでできます。

冒頭であったり、setup()のなかだったりと定義します。

そのとき、本やネットによって同じ内容のスケッチ(コード)なのに定義の仕方が異なっていると事が多々あります。

例えば以下などがそうです。

①#defiene ledpin 13
②const int ledpin = 13;

スケッチ(コード)的には、どちらで定義してもコンパイラエラーもでることはありません。

また、上記の後に同じ内容のスケッチ(コード)をかいたとしても同じように動作します。

 

ここで、ふと思うわけです。

どっちがいいの?

 

#defineについて

まずは、#defineについて確認していきます。

 

  • #defineはプログラム中の定数に対して名前を付けることができる
  • #defineで定義された定数は、コンパイル時に定義した値へ置きかえられる
  • チップ上のメモリ(RAM)を消費しない

構文例は以下となります。

#define 定数名 値
※最後に「;」はつきませんので注意!

 

#defineを使ったサンプルスケッチ(コード)がこちら。

単純なLEDのON/OFFです。

//サンプル1 #defineの場合

#define ledpin 13

void setup() {
pinMode(ledpin, OUTPUT); //13番ピンをOUTPUT指定
}

void loop() {
digitalWrite(ledpin, HIGH); //13番ピンをHIGH
delay(1000); //1秒待つ
digitalWrite(ledpin, LOW); //13番ピンをLOW
delay(1000); //1秒待つ
}

このスケッチでは、#defineによりコンパイル時にledpinという変数が全て13に置き換えられます。

 

constについて

次に、constについて確認していきます。

 

  • 変数を読み取り専用にする
  • 型を持つ変数として使えるが、値は変更できない
  • constで定義した変数に値を代入しようとするとコンパイルエラーになる
  • constを付けた変数はスコープのルールに従う

スコープのルールに関しては、下記をご確認ください。

とても大事なルールです。

 

constを使ったサンプルスケッチ(コード)がこちら。

単純なLEDのON/OFFです。

//サンプル1 #defineの場合

const int ledpin = 13;

void setup() {
pinMode(ledpin, OUTPUT); //13番ピンをOUTPUT指定
}

void loop() {
digitalWrite(ledpin, HIGH); //13番ピンをHIGH
delay(1000); //1秒待つ
digitalWrite(ledpin, LOW); //13番ピンをLOW
delay(1000); //1秒待つ
}

最初の変数の定義の仕方がことなるだけで、スケッチ(コード)の動作としてはまったく同じです。

 

これが、本だったりネットに転がってるスケッチ(コード)だったりでマチマチなわけです。

 

#defineとconstについて

公式リファレンスでは#defineよりもconstを使うことを推奨しています。

理由はconstで定義された変数はスコープのルールに従うため。

※しつこいですが、Arduino 入門 番外編 10 変数のスコープ(ローカル変数、グローバル変数)をご確認ください。

 

スコープのルールに従うというのは、間違いやミスを少なくできますよということにつながります。

#defineとても便利です。

しかし、その便利さが欠点でもあります。

それは、定義した変数が全て置き換えられるということ。
※利点でもありますが・・・。

 

#defineで定義した変数は、その変数がどこにいようともソースファイルをテキストのように扱い文字列の置換をしてしまうのです。

そう、これは意図しない置換をしてしまうことがあるということにつながります。

短いコードであれば、全体を把握できるので問題ありません。

しかし、コードが長くなれば長くなるほど把握するのに限界があります。

そのため、スケッチ(コード)はスコープのルールを意識して書くことが大事です。

これが、constを推奨している理由です。

 

考えてみてください。

スケッチ(コード)が長くなるため、繰り返し処理する部分を関数化したとします。

その関数の中に対して#defineで定義された変数と同じ変数を使っていたらどうなるでしょう。

やはり、置換が行われてしまいます。

ちょっと考えると置換が行われる範囲がおそろしいですよね・・・。

 

ちなみに、関数化に関しては以下にて解説しています。

興味のある方は覗いてみてください。

 

ということで、管理人は以下のように考えます。

初級者レベルのうちは基本はconstを使てスケッチ(コード)を書くことに慣れる。
中級、上級レベルになって、#defineの意味を理解したうえで使う。

管理人は、本日からconstを使うことを基本とします。

 

#defineって何?

じゃ、#defineってなんだろうって思いますよね。

一言でいうと、マクロです。

マクロはconst定数のようにデータの型をもちません。

コンパイル時にスケッチ(コード)の該当箇所を置換するマクロ機能です。

 

もっと詳しく解説したいとことですが・・・

管理人の知識では、この程度の解説が限界です。

 

#defineは何に使うんだ!

何に使うのでしょう・・・。

自問自答中です。

 

Arduinoのスケッチ(コード)に関しては#defineを使わないでも当面大丈夫と考えています。

 

まとめ

Arduino 入門 番外編 15 【#define】と【const】

いかがだったでしょうか?

 

Arduinoに色んなことをさせようと考えると、スケッチ(コード)がどんどん複雑になっていきます。

これからは#defineを使わずに、スケッチ(コード)を書くようにしたいと考えます。

Arduino 入門 番外編 09 スケッチ(コード、プログラム)の関数化

Arduino 入門 番外編 10 変数のスコープ(ローカル変数、グローバル変数)

とあわせて、わかりやすいスケッチを作成するように意識してみましょう。

 

スケッチ(コード)のデバック時に効果が実感できるはずです!

 

次回の番外編も、スケッチについて情報を発信したいと考えています。

 

最後に

疑問点、質問などありましたら気軽にコメントください。

この電子部品の解説をしてほしい!などなどなんでもOKです。

リンク切れ、間違いなどあればコメントいただけると助かります。

 

Arduino入門編、番外編、お役立ち情報などなどサイトマップで記事一覧をぜひご確認ください。

 

Arduino入門編で使用しているUNOはAmazonにて購入可能です。

互換品とは言え、Arduinoはオープンソース。

複製して販売するのもライセンス的に問題なし。

 

そのため互換品の品質も悪くなく、それでいて値段は安いです。

正規品本体の値段程度で豊富な部品が多数ついています。

 

学習用、遊び用、お試し用には安価な互換品がおすすめです。

 

 

上記のものでも十分に多数の部品が入っていますが、最初からもっと多数の部品が入っているこちらもお勧めです。

 

Amazonでお得に買う方法

Amazonでお得に購入するなら、Amazonギフト券がおすすめです。

現金でチャージするたびに、チャージ額に応じたポイントが付与されます。

最大2.5%!!!(Amazonプライム会員ならさらにお得)

チャージ額(一回分) 一般 プライム会員
5,000円~19,999円 0.5% 1.0%
2,0000円~39,999円 1.0% 1.5%
40,000円~89,999円 1.5% 2.0%
90,000円~ 2.0% 2.5%

さらに、初回チャージで1000ポイントもらえるキャンペーンも実施中!

\Amazonギフト券 1000ポイントキャンペーン/
Amazonチャージ 初回購入で1000ポイントキャンペーン

 

補足情報
コンビニ・ATM・ネットバンクが対象
購入は1円単位で可能

コメント

  1. lobin より:

    個人的に、Arduinoやってて#defineの使い道で一番多いのは#ifdefと合わせる方法ですね

    #define DEBUG
    void setup(){
    #ifdef DEBUG
    Serial.begin(115200);
    Serial.println(“Debug enabled”);
    #endif
    }

    こうすると、’DEBUG’が定義されているので”Debug enabled”とシリアル出力されます
    #define DEBUGの部分を削除すると#ifdef~#endifまでのシリアル出力に関する部分はコンパイルされないので、シリアル出力もされません
    ProMiniみたいな処理能力や容量の小さい物、スケッチやライブラリが長い場合も、あると便利です。これだけは代用が利きませんし。

    • omoroya omoroya より:

      コメントありがとうございます。
      #defineと#ifdefの組み合わせ、便利ですね。
      下記、なるほどと思いました。
      >ProMiniみたいな処理能力や容量の小さい物、スケッチやライブラリが長い場合も、あると便利です。
      プログラムは、あまり専門ではないのでコメントいただけるととても助かります。
      ありがとうございました。

  2. URK より:

    Arduino&C初心者です。ありがとうございます助かります
    定数をどっちで定義すればいいのか悩んでました。1つスッキリしました。
    コンパイルした時のメッセージ重要だったのですね、今まで無視していたのが、1つ理解が進みました。

タイトルとURLをコピーしました