構造体/共用体/列挙体
構造体
構造体 (structure) は,1 つの変数で複数のデータを扱えるようにしたデータ型です。
次のプログラムは,長方形を表す rectangle 構造体を定義したものです。
#include <stdio.h>
/* 長方形を表す構造体 */
struct rectangle {
int width; /* 幅 */
int height; /* 高さ */
};
int main(void)
{
struct rectangle rect; /* rectangle 構造体の変数を宣言 */
rect.width = 300;
rect.height = 400;
return 0;
}
struct rectangle { ... }; と定義された構造体の変数を宣言するには, struct rectangle rect; と書きます。
あるいは,構造体の定義と同時に struct rectangle { ... } rect; と書いて変数を宣言することもできます。
構造体の各メンバにアクセスするには,ドット演算子を使って rect.width のように書きます。
次のプログラムは,長方形の面積を求める getarea 関数を加え,その中で構造体へのポインタを使用しています。
#include <stdio.h>
typedef struct rectangle {
int width;
int height;
} Rectangle;
int getarea(Rectangle *rect)
{
return rect->width * rect->height;
}
int main(void)
{
Rectangle rect;
rect.width = 300;
rect.height = 400;
printf("面積: %d\n", getarea(&rect));
return 0;
}
構造体のコピーにはコストが掛かるため,ポインタ渡しがよく使われます。
構造体へのポインタから構造体のメンバにアクセスするには,アロー演算子 -> を使って rect->width と書きます。
これは (*rect).width のシンタックスシュガーです。
また,構造体の各メンバのサイズをビット単位で指定することができます。
次のプログラムは,ファイルのアクセスモードを表す構造体 AccessMode を定義したものです。
メンバ変数 read, write にはそれぞれ 1 ビットが割り当てられています。
typedef struct {
int read : 1;
int write : 1;
} AccessMode;
int main(void)
{
AcccessMode am;
am.read = am.write = 1;
return 0;
}
共用体
構造体によく似たデータ型として,共用体 (union) があります。
共用体のメンバは,同じメモリ領域を共有します。
#include <stdio.h>
union bytes {
int n;
char c[4];
};
int main(void)
{
union bytes u;
u.c[0] = 0x89;
u.c[1] = 0xAB;
u.c[2] = 0xCD;
u.c[3] = 0xEF;
printf("%X\n", u.n);
return 0;
}
EFCDAB89
この出力結果は,32-bit リトルエンディアン機における例です。
列挙体
列挙体 (enumeration) は整数定数を列挙したもので,複数の選択肢を表すのに使われます。
次のプログラムは,曜日を表す dayofweek 列挙体を定義したものです。
#include <stdio.h>
enum dayofweek {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY,
};
int main(void)
{
enum dayofweek day = TUESDAY;
switch (day) {
case SUNDAY:
printf("It's a holiday.\n");
break;
default:
printf("It's a weekday.\n");
break;
}
return 0;
}
列挙定数 (MONDAY, TUESDAY, ...) には,デフォルトの整数 (0, 1, ...) が付番されます。
割り当てる整数を変更するには,列挙定数の定義において MONDAY = 1 などと書きます。