【C言語】異なる型をまとめて扱う方法【構造体の使い方】

C言語

この記事では、C言語の構造体について解説します。構造体を使うことで、異なる型の変数を一つの型にまとめて管理することができます。

この記事で学べること
  • 構造体の使い方
  • 構造体のポインタ
  • 構造体の配列

構造体の使い方

それでは、C言語での構造体の使い方を見ていきましょう!

定義

構造体は、structキーワードを使って定義します。

struct 構造体タグ名 {
    型 メンバ1;
    型 メンバ2;
    ・
    ・
    ・
};
POINT
  • 型名を構造体タグ名と呼びます
  • 構造体内に定義された変数をメンバと呼びます
  • 最後の;を忘れないように!

宣言

構造体を使用するには、構造体の型の変数を宣言する必要があります。

struct 構造体タグ名 変数名;
POINT
  • 構造体の型の変数は構造体変数と呼ばれたりする

初期化

構造体を初期化するには、メンバの数だけデータを渡します。

struct 構造体タグ名 変数名 = {データ1, データ2, ... データN};

メンバにアクセス

メンバにアクセスするには、.を使って構造体変数名とメンバ名をつないでアクセスする。

構造体変数名.メンバ名;

サンプル

構造体を定義して使ってみましょう。

#include <stdio.h>

struct person {
    char *name;  // 名前
    int age;     // 年齢
};

int main(void) {

    // 宣言
    struct person mike;
    // 以下のように宣言・初期化できます。
    // struct person mike = {"Mike", 24};
    
    // メンバを1つずつ初期化
    mike.name = "Mike";
    mike.age = 24;

    // 出力
    printf("名前: %s, 年齢: %d\n", mike.name, mike.age);
}

実行結果

名前: Mike, 年齢: 24

typedefを使って宣言時にstructを省略する

typedefキーワードを使うことで、構造体宣言時にstructを省略できます。

新しい名前を付ける

構造体定義後にtypedefで新しい名前を付けることで、structを省略できます。

定義

以下のように定義します。

typedef struct 構造体タグ名 付ける名前;

サンプル

以下のコードでは、構造体personstruct無しで宣言できるようにしています。

struct person {
    char *name;  // 名前
    int age;     // 年齢
};

// 新しい名前を付ける(タグ名と同じでも問題ない)
typedef struct person person;

int main(void) {

    // struct無しで宣言できる
    person mike;
}

構造体定義時にtypedefを使う

typedefを使いながら構造体を定義することで、structを省略して宣言できます。

定義

構造体とtypedefを同時に定義することができます。

typedef struct 構造体タグ名 {
    型 メンバ1
    型 メンバ2
    ・
    ・
    ・
} 付ける名前;

サンプル

構造体persontypedefを使いながら定義しています。

// typedefを使いながら構造体定義
typedef struct person {
    char *name;  // 名前
    int age;     // 年齢
} person;


int main(void) {

    // struct無しで宣言
    person mike;
}

構造体タグ名を省略する

typedefを使いながら構造体を定義する際に、構造体タグ名を省略することができます。この方法が一番簡潔に構造体を使えます。

定義

構造体タグ名を省略して定義します。

typedef struct {
    型 メンバ1;
    型 メンバ2;
    ・
    ・
    ・
} 付ける名前;

サンプル

構造体personを書き直してみます。

typedef struct {
    char *name;  // 名前
    int age;     // 年齢
} person;

int main(void) {

    // 宣言
    person mike;
}

構造体を関数で使う

構造体を関数の引数や戻り値に使うことで、一度に複数の値を受け渡しすることができます。

サンプル

引数に構造体を受け取る関数を定義して呼び出しています。

#include <stdio.h>

typedef struct {
    char *name;  // 名前
    int age;     // 年齢
} person;

// 引数にpersonを受け取る関数
void print(person p){
    printf("名前: %s, 年齢: %d\n", p.name, p.age);
}

int main(void) {

    // 宣言・初期化
    person mike = {"Mike", 24};
    
    // 引数にperson型の変数を渡す
    print(mike);
}

実行結果

名前: Mike, 年齢: 24
POINT
  • tyepdefを使って宣言していない場合は、タグ名の前にstructを付けます
  • C言語は、構造体は値型で全ての値がコピーされます。なので、呼び出し側には影響を及ぼしません

構造体のポインタ

構造体はポインタとして扱うこともできます。ポインタの宣言方法は、通常の変数となんら変わりません。

【C言語】ポインタとはなんぞや?【ポインタの使い方】【C言語】ポインタとはなんぞや?【ポインタの使い方】

ポインタ引数

構造体はポインタ引数を使って受け渡しすることで、以下のようなメリットがあります。

関数内で値を変更できる

戻り値以外にも外部に影響を及ぼすことができる。

関数呼び出しの高速化

構造体は値渡しなので、全ての値をコピーして関数に渡します。メンバが1つ2つなら問題ありませんが、大きな構造体の場合はコピーに時間がかかります。その点、ポインタを使う場合では、構造体の先頭のアドレスを渡すだけで良いので高速処理が可能です。

定義

通常のポインタ引数と変わりません。

型名 関数名(型名 *ポインタ){
    // メンバにアクセス
    ポインタ->メンバ名;
}
POINT
  • アロー演算子(->)でメンバにアクセスすることを忘れずに!

呼び出し

&を使ってアドレスを渡します。

関数名(&変数);

サンプル

構造体をポインタ引数に渡して処理してみましょう!

#include <stdio.h>

typedef struct 
{
    char *name;
    int age;
} person;


void print(person *p){
    printf("名前: %s, 年齢: %d\n", p->name, p->age);
}

int main(void) {

    // 宣言・初期化
    person mike = {"Mike", 24};

    print(&mike);
}

実行結果

名前: Mike, 年齢: 24

構造体の配列

構造体も配列を使って宣言することができます。

宣言

structを記述する以外に他の型との違いはありません。

struct 構造体タグ名 変数名[要素数];
POINT
  • typedefを使って宣言してある場合はstructを省略できます

初期化

以下のように初期化します。

struct 構造体タグ名 変数名[要素数] = 
{
    {データ1-1, データ1-2, ..., データ1-N},
    {データ2-1, データ2-2, ..., データ2-N},
    ・
    ・
    ・
};
POINT
  • 要素数を指定せず空白にしておくと、初期化した数が自動で割り当てられる

メンバにアクセス

メンバにアクセスするには、以下のようにします。

構造体変数名[インデックス].メンバ名;

サンプル

構造体の配列を宣言・初期化・出力してみましょう。

#include <stdio.h>

typedef struct 
{
    char *name;
    int age;
} person;


void print(person p[], int length){
    for(int i = 0; i < length; ++i){
        printf("名前: %s, 年齢: %d\n", p[i].name, p[i].age);
    }
}

int main(void) {

    // 構造体の配列の宣言・初期化
    person persons[] = {
        {"Mike", 24},
        {"Sam", 18},
        {"Jason", 56}
    };

    // personsの長さ
    int length = sizeof(persons) / sizeof(persons[0]);

    print(persons, length);
}

実行結果

名前: Mike, 年齢: 24
名前: Sam, 年齢: 18
名前: Jason, 年齢: 56

まとめ

この記事では、C言語の構造体について解説しました。

おさらい

以下のコードを見て、今回の内容をおさらいしてみてください。よくわからない箇所があったら記事を読み返してみましょう!

#include <stdio.h>

// personを出力するだけの関数形式マクロ
#define print(p) printf("name: %s, age: %d\n", p.name, p.age)

// 構造体定義
typedef struct {
    char* name;
    int age;
} person;

// 誕生日の関数
void birthday(person* p){
    p->age++;
}

int main(void){

    // 構造体の初期化
    person mike = {"Mike", 24};
    print(mike);

    birthday(&mike);
    print(mike);
    
    return 0;
}

実行結果

name: Mike, age: 24
name: Mike, age: 25

関数や関数形式マクロについては以下を参照してください。

【C言語】関数の定義方法と使い方【C言語】関数の定義方法と使い方

C言語でデータをまとめて扱いたい場合、配列か構造体を使います。配列は、同じ型の要素しか格納できないので、異なる型を扱いたい場合は、構造体を使ってデータをまとめましょう。さらに、構造体の配列を使うことで、より複雑にデータを扱うことができます。

それでは今回の内容はここまでです!ではまたどこかで〜( ・∀・)ノ

タイトルとURLをコピーしました