構造体

  • structは、一連の他のデータ型から作成したデータ型である
  • structは固定長である
  • structフィールドは、.<field_name>という構文を使って名前でアクセスする
  • structフィールドは、コードの順序と同じ順序でメモリに格納される
  • structは入れ子にできる
  • typedefはデータ型のエイリアスを作成する
  • structでtypedefを使う場合は、structの名前を省略できる

構造体とポインタ

  • 関数を呼び出すと、値はパラメータ変数にコピーされる
  • 他の型と同様に、structへのポインタを作成できる
  • pointer->fieldは(*pointer).fieldと同じである

共用体とビットフィールド

  • unionは、同じメモリ位置に異なるデータ型を格納できる
  • 指示付き初期化子は名前でフィールド値を設定する
  • 指示付き初期化子はC99で使える。Objective-Cでは使えるが、C++ではサポートされていない。
  • 中括弧({})で値を指定してunionを宣言すると、その値を最初のフィールドの型で格納する
  • unionのあるフィールドに書き込んだ値を別のフィールドとして読みだす場合、コンパイラは警告を出さない
  • enumはシンボルを格納する
  • ビットフィールドは任意のビット数でフィールドを格納できる
  • ビットフィールドはunsigned intとして宣言すべきである
#include <stdio.h>

typedef enum {
    COUNT, POUNDS, PINTS
} unit_of_measure;

typedef union {
    short count;
    float weight;
    float volume;
} quantity;

typedef struct {
    const char *name;
    const char *country;
    quantity amount;
    unit_of_measure units;
} fruit_order;

void display(fruit_order order)
{
    if (order.units == PINTS)
        printf("%.2fパイントの%sです\n", order.amount.volume, order.name);
    else if (order.units == POUNDS)
        printf("%2.2fポンドの%sです\n", order.amount.weight, order.name);
    else
        printf("%i個の%sです\n", order.amount.count, order.name);
}

int main()
{
    fruit_order apples = {"りんご", "イギリス", .amount.count=144, COUNT};
    fruit_order strawberries = {"いちご", "スペイン", .amount.weight=17.6, POUNDS};
    fruit_order oj = {"オレンジジュース", "アメリカ", .amount.volume=10.5, PINTS};
    display(apples);
    display(strawberries);
    display(oj);

    return 0;
}