■構造体の基本

Last modified: Sun Jun 16 2024
このページは,基礎工学部システム科学科機械科学コース2年生向けの 「情報科学演習」における演習4の教材の1つです.

「配列」は「同じ型」の変数をたくさんまとめて使いたい場合に用い, 各要素に「番号」でアクセスする.

「構造体」を使うと,「異なる型」をまとめて使ったり, その各要素(メンバという)を「名前」でアクセスできる.

構造体を使うには2段階の宣言が必要.
「構造体テンプレート」の宣言と「構造体変数」の宣言.

●構造体テンプレートの宣言

    struct タグ名 {
        型名1  メンバ名1;
        型名2  メンバ名2;
        ...;
     };
    (例) 2次元ベクトル
    struct vector {
         double x;
         double y;
    };

    (例) 個人データ
    struct personal {
         int    age;
         double height;
         double weight;
         char   name[20];
    };
構造体テンプレート宣言はデータ形式を定義しただけ, 実際に記憶する領域はまだ用意されない.

●構造体変数の宣言

    struct タグ名 構造体変数名;
    (例)
    struct vector    v1, v2, v3;
    struct personal  hosoi, matsui, miyazaki, matsushita;

構造体変数を宣言することによって初めて記憶領域が用意され, 実際に構造体を使うことができる.

タグ名を省略して,テンプレートと変数の宣言を同時に行うこともできるが, あまり使わない(覚えなくてよい).

    struct {
        型名1  メンバ名1;
        型名2  メンバ名2;
        ...;
     } 構造体変数名;
    struct {
         double x;
         double y;
    } v1, v2, v3;

●メンバへのアクセス

    構造体変数名.メンバ名
この形式で,各メンバに対する代入と参照ができる.
    (例)
    struct vector v1, v2;
    v1.x = 200.0;
    v1.y = 300.0;
    v2.x = 3.0*v1.x;
    v2.y = 3.0*v1.y;

    (例)
    struct personal a;
    a.age    = 22;
    a.height = 178.0;
    a.weight = 65.0;
    strcpy(a.name, "Nishikawa");
    /* strcpy()は文字列のコピーを行う標準ライブラリ関数 */

例4-1 example41.c

1人分の成績データを表現する構造体を定義したプログラム.
文法例を示しただけで,このプログラムでは構造体のありがたみはわからない.
struct seiseki {                        構造体テンプレートの宣言
    int    sugaku;
    int    eigo;
    int    kokugo;
    int    kesseki;
    double heikin;
    int    gokaku;
};
    .....

    struct seiseki ichiro, jiro;        構造体変数の宣言

●初期値

宣言の際に変数にまとめて初期値を与えることができる.
    struct タグ名 構造体変数名 = {メンバ1の値, メンバ2の値, ...};
配列の場合と同じように波括弧を用いたこの書式は初期値の設定にしか使えない.
    (例)
    struct vector v = {1.0, 2.0};
    struct personal a = {20, 175.3, 65.1, "木曾幸太郎"};

●代入

「=」を使って,構造体変数の内容を別の(タグ名が等しい)構造体変数に「代入」できる. 全てのメンバがコピーされる.「代入」は,構造体全体で唯一可能な演算である. それ以外の「+,-,*,/」「==, <, >」などの演算は許されていない.
    (例)
    struct vector v1, v2, v3;

    v1.x = 10.0;
    v1.y = 20.0;
    v2 = v1;         ← 可能
    v3 = v1 + v2;    ← 許されない (「+」が不可)

●配列との比較

構造体のメンバが全て同じ型であれば,同等の変数は配列を使っても実現できる. しかし,プログラムの読みやすさ,意味のわかりやすさは,構造体の方が優れている. また,配列は丸ごとの代入が許されていない.
    (例)
    double v1[2], v2[2], v3[2];

    v1[0] = 10.0;
    v1[1] = 20.0;
    v2 = v1;         ← 許されない.
    v3 = v1 + v2;    ← 許されない.

●構造体を含む構造体

構造体を含む構造体を定義することができる.
    (例)
    struct point {    /* 2次元空間の点 */
        double x;
        double y;
    };
    struct segment {  /* 2次元空間の線分 */
        struct point start
        struct point end;
    };
    struct segment a;

    a.start.x = 1.0;
    a.start.y = 2.0;
    a.end.x = a.start.x + 10.0;
    a.end.y = a.start.y + 10.0;

●配列

構造体の配列変数を定義することができる.
    struct タグ名 構造体配列名[要素数];
要素数が多い場合は,staticを前に付加して,静的変数として定義するべきである. 自動変数の領域はあまり大きくないからである.
    (例)
    struct vector    v[10];
    static struct personal  table[100];

●関数

構造体を関数の引数や戻り値に使うことができる.
ここからが構造体の本領発揮である.

例4-2 example42.c

1人分の成績データを表現する構造体を定義し,関数の引数や戻り値に用いる.
struct seiseki {                        構造体テンプレートの宣言
    int    sugaku;
    int    eigo;
    int    kokugo;
    int    kesseki;
    double heikin;
    int    gokaku;
};
     .....

    static struct seiseki seito[DMAX];  構造体配列変数の宣言
                                        (容量が大きいので静的に領域確保)


struct seiseki                          構造体を戻り値とする関数
nyuryoku(void)
{
    .....
}

void
hantei(struct seiseki a[], int n)      構造体の配列を引数とする関数
{
    .....
}

void
hyoji(struct seiseki s)                構造体を引数とする関数
{
    .....
}

[演習4のインデックス] [前の教材] [次の教材(新しい型名の定義)]