名前付き整数定数を並べた列挙体

こんにちは、めのんです!

前回予告したように今回は「列挙体」を解説することにします。
構造体、共用体と来て今度は列挙体ですので、なんとなく似た感じのものじゃないかなと思われたかもしれませんね。

列挙体はそんなに難しい内容でも複雑な内容でもないので、今回はさらっと済ませたいと思います。

列挙体とは

実際、列挙体は構造体や共用体と似たところもあるんですけど、見た目も機能もかなり違います。

まず、列挙体の型は「列挙型」というんですけど、整数型なんですよね。
構造体は配列なんかと同じで集成体でしたし、共用体は集成体ではないですが算術型やポインタ型ではない特別な型でした。
でも、列挙型は整数型なんです。

一応異なる列挙型はそれぞれ別の型にはなるんですけど、整数型である以上、サイズがいくつで符号付きか符号無しかで特徴が決まってくる点は同じです。

じゃあ列挙体、そして列挙型にはどんな意味があるんでしょう?
それは整数定数に名前を付けてひとまとめの型にできることなんです。

それでは実際に列挙対の定義を見ていきましょう。

列挙体の定義

列挙体の定義は次のように書きます。

enum day_of_week
{
  Sunday,
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday
};

上のサンプルコードでは1週間の曜日を列挙体にまとめてみました。
このサンプルでは、Sundayが整数値の0に、以下1, 2, 3, …, 6と順に値が振られます。

列挙体を使えばこのように整数定数に名前を付けることができますので、ソースコード上でマジックナンバーを使わなくても済むようになります。

さきほどは0から順位値を振るだけでしたが、好きな値を設定することもできます。
たとえばこんな風にです。

enum day_of_week
{
  Sunday,
  Monday,
  Tuesday,
  Wednesday = 10,
  Thursday,
  Friday,
  Saturday
};

今度はWednesdayだけ値が10になるように設定してみました。
このように明示的に値を設定することができます。

この場合、Wednesdayが10ですのでThursdayはその次の11、以下12, 13, …と続きます。
Wednesdayより前は通常どおり0から順番に値が振られます。

用語の説明

列挙体の宣言に使ったenumのあとに続く名前は「タグ」です。
構造体や共用体のタグと同じですので、タグ名前空間に属すことになります。

SundayやMondayは列挙体の「メンバ」ですが、一般的には「列挙定数」と呼びます。
また、Wednesday = 10のように=以下の値がある場合はそれも含めて「列挙子」と呼びます。

細かい用語に関しては「まあそんなもんだ」ぐらいの理解で十分だと思います。

列挙体の使い方

列挙体の使い方は簡単ですが、列挙定数を名前で扱える程度で単なる整数だということを忘れないでください。

#include <stdio.h>

enum day_of_week
{
  Sunday,
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday
};

int main(void)
{
  enum day_of_week x = Sunday;  // 列挙定数で初期化
  enum day_of_week y = 123;     // 普通の整数値でも初期化できてしまう。
  int z = x;  // 列挙型からint型に暗黙的な型変換 

  printf("%d\n", x);  // 0が出力される。
  return 0;
}

列挙定数の型はint型になります。
名前は付いていますがint型ですので、普通の123のような整数定数と性質は何も変わりません。

列挙型は「enum タグ」が型名になります。
列強型は整数型ですが、列挙定数をすべて表現することができるchar、符号付き整数型、符号無し整数型のどれかと同じ性質を持ちます。

単なる整数に過ぎませんから、さきほどのサンプルの20行目のようにprintf関数で列挙型の値を出力すると整数値しか出力されません。
列挙定数の名前が出力されることはありませんので、もし名前が必要なら自分で変換する必要があります。


今回の解説は以上となります。
本当はもっと細かい内容があるんですけど、普段使うことはまずないような知識になるので割愛しました。
次回は不完全型を説明しようと思います。
どうぞご期待ください!