構造体とは
C言語での構造体とは、ひとつの名前でまとめられた、いくつかの異なった型の変数の集まりです。異なった型を格納できる点が配列と異なっています。
構造体の中で命名された変数はメンバと呼ばれます。そして、このメンバは通常互いに関連のあるものになります。例えば、人に関する構造体なら、氏名、年齢、性別、身長、体重などがメンバとなるでしょう。このように関連のある属性をひとつの単位として扱え、組織化できるところが構造体の利点です。
また、C言語はオブジェクト指向言語ではありませんが、構造体をうまく利用することにより、オブジェクト指向的な設計をすることも可能です。
構造体の簡単な使用例
#include <stdio.h>
#include <string.h>
/* 従業員の属性をEmployee構造体として宣言 */
struct Employee
{
/* メンバ変数の定義 */
int number; /* 従業員番号 */
char name[51]; /* 氏名 */
int salary; /* 給与 */
};
int main(int argc, char *argv[])
{
/* 構造体を定義 */
struct Employee e;
/* 構造体の各メンバに値を代入 */
e.number = 100;
strcpy(e.name, "Taro Yamada");
e.salary = 200000;
/* 構造体の内容を出力 */
printf("Number:%d¥nName:%s¥nSalary:%d¥n", e.number, e.name, e.salary);
return 0;
}
#include <stdio.h>
#include <string.h>
ヘッダのインクルードです。strcpy()を使うのでstring.hも必要です。
/* 従業員の属性をEmployee構造体として宣言 */
struct Employee
{
/* メンバ変数の定義 */
int number; /* 従業員番号 */
char name[51]; /* 氏名 */
int salary; /* 給与 */
};
構造体の型を宣言しています。型の宣言だけですのでメモリの割当は行われていません。構造体の型の宣言は次のような形になっています。
struct タグ名 {
データ型 メンバ名;
:
};
タグ名で構造体の型の宣言に名前をつけることができます。タグ名をつけることにより、以降、{}(大かっこ)内の宣言部分の略称として使用することができます。
構造体のメンバとタグの名前は、他の変数名と同じであってもかまいません。また、異なる構造体で同じメンバ名をつかってもかまいません。
タグ名は省略できます。以下のような記述も可能です。この場合は変数eの定義になりますので、メモリの割当が行われます。
struct {
int number;
char name[51];
int salary;
} e;
int main(int argc, char *argv[])
{
/* 構造体を定義 */
struct Employee e;
構造体を使用した変数の定義は上記のように行います。タグ名が使用できますので、メンバ変数の記述はいりません。
/* 構造体の各メンバに値を代入 */
e.number = 100;
strcpy(e.name, "Taro Yamada");
e.salary = 200000;
/* 構造体の内容を出力 */
printf("Number:%d¥nName:%s¥nSalary:%d¥n", e.number, e.name, e.salary);
return 0;
}
構造体の各メンバにアクセスするには上記のように.(ピリオド)を使用します。また、定義時に初期化を行いたい場合は下記のように記述します。
struct Employee e = {
100, "Taro Yamada", 200000
};
構造体の代入
同じ型であれば、各メンバ単位ではなく構造体全体を代入することができます。
struct Employee e1 = {
100, "Taro Yamada", 200000
};
struct Employee e2;
e2 = e1;
構造体の入れ子
struct Salary
{
int regular; /* 基本給 */
int allowance; /* 手当 */
};
struct Employee
{
int number; /* 従業員番号 */
char name[51]; /* 氏名 */
struct Salary salary; /* 給与 */
};
構造体の配列・ポインタ
構造体の配列とポインタの使用例を書いてみます。構造体へのポインタから各メンバを参照するには、.(ピリオド)ではなく->(アロー演算子)を用いることに注意してください。
#include <stdio.h>
struct Employee
{
int number; /* 従業員番号 */
char name[51]; /* 氏名 */
int salary; /* 給与 */
};
int main(int argc, char *argv[])
{
/* 構造体を宣言 */
struct Employee e[] = {
{100, "Taro Yamada", 200000},
{101, "Jiro Sato", 220000},
{102, "Saburo Nakamura", 180000},
{103, "Hanako Yoshida", 160000},
{104, "Yoshiko Saito", 240000},
{0, "", 0} /* エンドレコード */
};
/* 構造体のポインタを宣言 */
struct Employee *e_ptr;
/* ポインタに構造体のアドレスをセット */
e_ptr = e;
/* 構造体の内容を出力 */
while (1) {
if (e_ptr->number == 0) {
/* エンドレコードなら処理終了 */
break;
}
/* 構造体の内容を表示 */
printf("%d,%s,%d¥n",
e_ptr->number, e_ptr->name, e_ptr->salary);
/* ポインタをインクリメントし */
/* 次の配列要素を指すようにする */
e_ptr++;
}
return 0;
}