組み込みマイコンのプログラムでは、入出力の処理を行うのが肝になるため、この入出力の名前をつけるのに列挙型を使用します。
列挙型はある関連するものに対して、変数名と数値を割り当てることができるものです。
例えば、犬や猫などの動物に対して、dogは0、catは1というふうに割り当てたいときに、列挙型を用いると便利です。
組み込みマイコンでは、エレベータで例を挙げると、入力や出力、走行フェーズやドアの動作フェーズなどに対して、列挙型をしようしています。
では、実際に列挙型をどんな風に使うのかをお話しします。
列挙型の宣言の仕方
まずは、宣言の仕方からです。これがないと何も始まりませんからね。
列挙型は構造体の宣言と似ています。enumというものを使います。
enum タグ名 { 列挙子1, 列挙子2, ・ ・ };
構造体ではenumのところがstructとなり、列挙子の部分がメンバ変数宣言になります。
タグ名はなくても構いません。列挙子は何も指定しなければ、0から順番に割り当てられます。
エレベータのプログラムで使用するフェーズを例に挙げますね。
enum run_phase { stop, start, run, dclr, };
停止中、起動準備、走行中、減速中という感じですね。実際にはいろんな制御があるため、もっと複雑です。
減速中のあとは、停止中に戻るので、この4つで、エレベータの走行の状態を表すことができます。
それらを用いて、いろんな状態監視をしています。ここでは、そのお話はしないことにします。
列挙型に話を戻しますが、stop は 0、start は 1、run は 2、dclr は 3 ということになります。
この列挙型をもつ変数は
enum run_phase phase;
と宣言すればいいです。そして、phase = stop;と代入するだけです。
列挙型に値を割り付ける
列挙型は、列挙子に何も指定しなければ、0から順番に割り当てられるとお話ししました。
これを割り付けなおすことができます。
enum run_phase { stop, start=10, run, dclr, };
startを10に割り付けました。何も指定しないときは、1になりますが、このように10にすることができます。
そして、start を 10 にしたことで、以降のrun は 11、dclr は 12 となります。ちなみに、stopは 9 にはならず、0 のままです。
影響するのは、あくまで、割り付け直した列挙子以降の列挙子です。
組み込みマイコンでは、入力の空きポートがあった場合に、そこには何も割り当てたくないので、わざとダミー列挙子を書くか、数値を割り当てなおすことで対応します。
enumと#defineとconst
enumを使用しなくても#defineやconst文で同じことは実現できます。
#define stop 0 #define start 1 #define run 2 #define dclr 3 const int stop = 0; const int start = 1; const int run = 2; const int dclr = 3;
上記のように記述すれば、enumと同等のプログラムになります。
しかし、enumを使わないと、stop, start, run, dclrが相互に関連しているという意図が伝わりにくくなるでしょう。
まとめ
列挙型enumについて、お話ししました。関連性のある固定データは、enumを使って、まとめておく方がよいと思います。
そのほうが、さらに追加で関連データが増えても、意識しなくても、+1された値になりますから、意図しない数値にはなりません。
それに、プログラムの意図が伝わりやすくなります。
しかし、#defineやconst文で記述することも可能です。
始めのうちは、あなたの思うようにプログラムを書いてみるといいでしょう。そうしているうちに、どう書くのが最善かを考えるようになってきます。そのときにenumがあったなと思い出せれば、それでよいと思います。