C言語で構造体を代入する方法

392, 2022-01-18

目次

C言語で構造体を代入する方法

C言語では構造体というデータ構造を扱うことができます。
構造体を使うと異なる型の変数を1つにまとめることができるので非常に便利です。

この構造体は変数などに代入することができます。
代入することで構造体のデータをコピーして複製することができます。

この記事ではC言語の構造体の代入について詳しく解説します

関連記事
C言語で構造体を比較する【memcmpの危険性】
C言語で構造体を引数に渡す方法
C言語の構造体をコピーする
C言語の構造体を関数で扱う
C言語の構造体のポインタの使い方

構造体変数に構造体変数を代入する

構造体で定義した変数を構造体変数と言います。
構造体変数はたとえば↓のように定義します。

struct Animal {
    int age;
    char name[40];
};

int main(void) {
    struct Animal cat = {20, "Tama"};
    return 0;
}

上記のコードのmain関数内のcatという変数が構造体変数になります。
この構造体変数catstruct Animal構造体の変数です。
struct Animalint age;char name[40];という変数を持っています。
この構造体内で定義している変数をメンバ変数と言います。

構造体変数を定義するときは↓のようにコードを書いて、メンバ変数を初期化します。

    struct Animal cat = {20, "Tama"};

上記の定義では、構造体変数catのメンバ変数ageには20という整数が、メンバ変数nameには"Tama"という文字列が保存されます。

この構造体変数catを別の構造体変数dogに代入してみます。
↓がコードです。

#include <stdio.h>

struct Animal {
    int age;
    char name[40];
};

int main(void) {
    struct Animal cat = {20, "Tama"};
    struct Animal dog = cat;  // 代入

    printf("cat age[%d] name[%s]\n", cat.age, cat.name);
    // cat age[20] name[Tama]

    printf("dog age[%d] name[%s]\n", dog.age, dog.name);
    // dog age[20] name[Tama]

    return 0;
}

上記のコードをコンパイルして実行すると↓の結果になります。

cat age[20] name[Tama]
dog age[20] name[Tama]

コードを見てみます。
まず構造体変数catを構造体変数dog代入してる部分です。

    struct Animal cat = {20, "Tama"};
    struct Animal dog = cat;

catにはage20, name"Tama"が設定されています。
この構造体変数を同じ構造体の変数、dogに代入しています。
構造体変数同士の代入では、そのメンバ変数はすべてコピーされます
int型のageはコピーされ、char型の配列nameもすべての要素がコピーされます。

char型の配列のコピーでは、文字とナル文字もコピーされるので、コピー先の配列も文字列として機能します。

構造体のメンバ変数が無数にあり、構造体が巨大な場合は代入によるコピーもそれなりにコストがかかります
ですがほとんどの場合は気にならないコストでしょう。
プログラム中で何度も呼び出す関数で巨大な構造体を代入していたら、もしかしたらボトルネックにはなるかもしれません。

構造体変数のアドレスをポインタ変数に代入する

構造体変数はポインタ変数にすることができます。
たとえば↓が構造体のポインタ変数の定義です。

    struct Animal *ptr = NULL;

この構造体のポインタ変数ptrに構造体変数のアドレスを代入するには↓のようにコードを書きます。

    struct Animal cat = {20, "Tama"};
    struct Animal *ptr = &cat;

&は変数のアドレスを取り出す演算子です。
上記のようにするとポインタ変数ptrに構造体変数catのアドレスが代入されます。

#include <stdio.h>

struct Animal {
    int age;
    char name[40];
};

int main(void) {
    struct Animal cat = {20, "Tama"};   
    struct Animal *ptr = &cat;

    printf("ptr->age[%d] ptr->name[%s]\n", ptr->age, ptr->name);
    // ptr->age[20] ptr->name[Tama]

    return 0;
}

構造体のポインタ変数からメンバ変数を参照するにはアロー演算子を使います。
ptr->ageptr->nameのようにメンバ変数を参照します。
ptrNULLの場合はプログラムがクラッシュする場合もありますのでその辺は注意が必要です。

構造体変数の配列の要素を代入する

構造体は配列としても定義することができます。

struct Animal {
    int age;
    char name[40];
};

int main(void) {
    // 構造体の配列
    struct Animal cats[] = {
        {20, "Tama"},  // 0番目の要素
        {30, "Mike"},  // 1番目の要素
        {40, "Bob"},  // 2番目の要素
    };
    return 0;
}

構造体の配列の要素同士は代入することができます
たとえば↑のcatsの0番目の要素を1番目の要素に代入してみると↓のようなコードになります。

#include <stdio.h>

struct Animal {
    int age;
    char name[40];
};

int main(void) {
    // 構造体の配列
    struct Animal cats[] = {
        {20, "Tama"},  // 0番目の要素
        {30, "Mike"},  // 1番目の要素
        {40, "Bob"},  // 2番目の要素
    };

    printf("代入前\n");
    printf("cats[0] age[%d] name[%s]\n", cats[0].age, cats[0].name);
    printf("cats[1] age[%d] name[%s]\n", cats[1].age, cats[1].name);

    // 0番目の要素を1番目の要素に代入
    cats[1] = cats[0];

    printf("代入後\n");
    printf("cats[0] age[%d] name[%s]\n", cats[0].age, cats[0].name);
    printf("cats[1] age[%d] name[%s]\n", cats[1].age, cats[1].name);

    return 0;
}

↑のコードをコンパイルして実行すると↓の結果になります。

代入前
cats[0] age[20] name[Tama]
cats[1] age[30] name[Mike]
代入後
cats[0] age[20] name[Tama]
cats[1] age[20] name[Tama]

代入前ではcats[1]age30になってます。
これが0番目の要素を1番目の要素に代入するとcats[1]age20になります。
これはcats[1]cats[0]のメンバがコピーされたからです。

また配列の要素は普通の構造体変数に代入することも可能です。

    struct Animal dog = cats[0];  // 代入

構造体変数を関数の引数に渡す(代入する)

関数の引数にも構造体変数を使うことができます。
たとえば↓のような関数です。

void func(struct Animal dog) {
    printf("dog age[%d] name[%s]\n", dog.age, dog.name);
}

この関数funcは引数にstruct Animal型の構造体変数を取ります。
(構造体引数とでも言いましょうか)

こういった関数に構造体変数を渡すと構造体変数同士の代入と同じ処理が行われます。

#include <stdio.h>

struct Animal {
    int age;
    char name[40];
};

void func(struct Animal dog) {
    printf("dog age[%d] name[%s]\n", dog.age, dog.name);
    // dog age[20] name[Tama]
}

int main(void) {
    struct Animal cat = {20, "Tama"};   
    func(cat);  // dogに代入
    return 0;
}

↑のコードをコンパイルして実行すると↓の結果になります。

dog age[20] name[Tama]

関数の引数に構造体変数をそのまま渡した場合は、代入と同じような処理になります。
func()の引数dogにはcatメンバがすべてコピーされます

おわりに

今回はC言語の構造体の代入について解説しました。
構造体の代入はコピー処理で実現されます。
コピーの特性をよく理解して使うようにしてください。

(^ _ ^)

たくさんコピーするぞ

(・ v ・)

パソコンは働き者

この記事のアンケートを送信する