本文へスキップ
BecomeCoder

C言語コース · 第7章 構造体と共用体 · レッスン30

unionとenum ― 領域を共有する型・名前つき定数

ブラウザで完結

導入

構造体はメンバ全部の分だけメモリを使います。一方、union(共用体)は複数のメンバが同じメモリ領域を共有する型で、どれか1つの値だけを保持できます。また enum(列挙型)を使うと、0, 1, 2, ... のような数値に名前をつけて読みやすくできます。

説明

union の定義は struct とまったく同じ書き方ですが、意味が違います。メンバは同じ場所に重なって置かれるので、sizeof はメンバの中で一番大きいものと同じになります。

#include <stdio.h>

union Data {
    int i;
    float f;
    char c;
};

int main(void) {
    union Data d;
    d.i = 65;
    printf("i=%d\n", d.i);
    printf("c=%c\n", d.c);        // 同じ場所を1バイトだけ文字として読む → 'A'(65のASCII文字)
    printf("size=%zu\n", sizeof(d));   // メンバの最大サイズ(構造体なら合計サイズになるところ)
    return 0;
}
flowchart TB
  subgraph S["struct(別々の場所)"]
    direction LR
    s1["i(4バイト)"]
    s2["f(4バイト)"]
  end
  subgraph U["union(同じ場所を共有)"]
    direction LR
    u1["i と f と c が<br/>同じアドレスを指す"]
  end

enum は名前つきの整数定数の集まりです。何も書かなければ 0 から順に振られます。

#include <stdio.h>

enum Color { RED, GREEN, BLUE };   // RED=0, GREEN=1, BLUE=2

int main(void) {
    enum Color c = GREEN;
    printf("%d\n", c);             // 1

    switch (c) {
        case RED:   printf("red\n");   break;
        case GREEN: printf("green\n"); break;
        case BLUE:  printf("blue\n");  break;
    }
    return 0;
}

REDGREEN は、実際にはただの int(0, 1, 2, …)ですが、名前がついているおかげで switchif の条件が「何を表しているか」を読みやすくなります。

やってみよう

union Datad.f = 3.14; を入れてから d.i を表示すると、期待した 3.14 にはならないことを確かめましょう(同じ場所を違う型として読んでいるためです)。enum Color の値を BLUE に変えて switch の結果が変わることも確かめてください。

演習

enum Weekday { SUN, MON, TUE, WED, THU, FRI, SAT }; を定義してください。enum Weekday day = WED; として、まず printf("%d\n", day); で数値を1行表示し、続けて if 文で daySUN または SAT なら「休日」、それ以外なら「平日」と表示してください(WED なら 3平日 の2行になります)。

ヒント1を見る

enum Weekday { SUN, MON, TUE, WED, THU, FRI, SAT };SUN=0 から順に番号が振られます。

ヒント2を見る

if (day == SUN || day == SAT) { ... } else { ... } の形で分けます。

実際に動かしてみよう

下のエディタにCを書いて「コンパイル & 実行」を押すと、ブラウザ内で本物のCコンパイラ(clang + dlmalloc)がその場でコンパイルして実行し、出力が表示されます。構造体・共用体・malloc/free・関数ポインタ・ファイル入出力などがそのまま動きます。本文の例を書き換えて試しながら進めましょう(初回だけコンパイラの読み込みに時間がかかります。以降はキャッシュされます。この回は標準入力(scanf)は使わず、値はコードに直接書きます)。

C/C++ — ブラウザ内で本物のコンパイラで実行

ブラウザ内で本物のC/C++コンパイラ(clang + libc++ / WebAssembly)を動かします。構造体・malloc/free・std::string・vector・クラス・テンプレート・STL などがそのまま実行できます(初回のみコンパイラの読み込みに時間がかかります。以降はブラウザにキャッシュされます)。
スクロールして表示された時点でも自動で読み込まれます。