上の定義によって、 word という新しいデータ型が使えるようになります。 これは unsigned short と同じです。 この定義の後から、 次のような変数宣言ができるようになります。typedef unsigned short word;
配列のように複数の要素を持ったデータ型を定義することもできます。word w;
上の例の場合、 vector は float 型の3個の要素を持つ配列のデータ型になります。 従ってこの定義の後、次のように変数宣言を行うと、 normal は3つの要素を持った配列変数として宣言されます。typedef float vector[3];
定義した型をもとに、さらに新しい型を作ることもできます。vector normal;
上によって定義された matrix は 3×3の要素を持つ2次元配列変数を宣言します。typedef vector matrix[3];
この例では、 配列変数 data[0] に身長、 data[1] に体重、 data[2] に胸囲を格納すると決めておけば、 data という配列変数ひとつで、 一人分のデータを保存することができます。float data[3];
次に、このデータに被験者の氏名も含めようと考えたとします。 身長や体重、胸囲は数値でしたから、 これらはいずれも float 型のデータとして統一できましたが、 氏名は文字列で表す必要があります。 これは float 型の配列である data に含めることはできません。
そう言う場合に、構造体というデータ型を用います。
struct kenshin {
char name[20];
float height;
float weight;
float bust;
} data;
変数の宣言(上の例では data)は省略できます。
この場合、構造体の定義のみを行います。
構造体の各要素を指定するには、 構造体変数名の後に .(ピリオド)に続けて要素名を書きます。 上の例で宣言された構造体変数 data の各要素は、 次のように指定します。
構造体を一度定義すれば、 同じ構造をもつ構造体変数は 構造体名(上の例では kenshin)のみを指定して宣言できます。/* i-dic による鈴木杏樹のデータ */ strcpy(data.name, "Anju Suzuki"); data.height = 161.0; data.weight = 43.0; data.bust = 81.0;
同じ構造体変数を別のところで宣言する必要がなければ、 構造体名も省略することができます。struct kenshin anotherData;
struct {
float x, y;
} point;
また typedef を使用して、
新しいデータ型を定義する方法もよく用いられます。
typedef struct {
char name[20];
float height;
float weight;
float bust;
} Kenshin;
構造体の変数の初期化の方法は、
配列の初期化に準じます。
struct kenshin miho = {
/* i-dic による菅野美穂のデータ */
"Miho Kan'no",
160.0,
40.0,
81.0
};
共用体は構造体に非常によく似ていますが、
各要素が同一のメモリを共用する点が異なります。
union kenshin {
char name[20];
float height;
float weight;
float bust;
} data;
従って、
共用体のひとつの要素に代入を行うと、
他の要素の内容は破壊されてしまいます。
このため、共用体では一度にひとつの要素だけが使用できます。
struct bitfield {
signed x:12;
unsigned y:4;
};
但し、精度は要素の型の精度を越えることはできません。
struct bitfield {
char x:12; /* ←エラー */
unsigned char y:4;
};
struct kenshin {
char name[20];
float height;
float weight;
float bust;
};
void sub(struct kenshin *p)
{
/* i-dic による永作博美のデータ */
strcpy((*p).name, "Hiromi Nagasaku");
(*p).height = 156.0;
(*p).weight = 42.0;
(*p).bust = 82.0;
}
int main(void)
{
struct kenshin nagasaku;
sub(&nagasaku);
}
構造体のポインタ変数の要素の指定は、
.(ピリオド)の優先順位が * よりも高いため、
上のように括弧を使う必要があります。
この記法は繁雑なので、 代わりに -> という演算子が用意されています。(*p).height = 156.0;
従って、上の例の関数 sub は、 下のように書くことができます。p->height = 156.0;
void sub(struct kenshin *p)
{
/* i-dic による永作博美のデータ */
strcpy(p->name, "Hiromi Nagasaku");
p->height = 156.0;
p->weight = 42.0;
p->bust = 82.0;
}