Categories: C言語

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

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

構造体を使うことで異なる型の変数を一つの型にまとめて管理することができます。

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

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

構造体の使い方

構造体は、structキーワードを使って以下のように定義します。

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

宣言

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

struct 構造体タグ名 変数名;

構造体の型の変数は、構造体変数と呼ばれたりする

初期化

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

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 構造体タグ名 付ける名前;

サンプル

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

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

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

int main(void) {

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

構造体定義時にtypedefを使う

typedef を使って構造体を定義することで struct を省略して宣言できます。以下のように定義することができます。

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

サンプル

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

// 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
  • tyepdef で宣言していない場合、タグ名の前に struct を付けます
  • C言語の構造体は値型で全ての値がコピーされます。なので、呼び出し側には影響を及ぼしません

構造体のポインタ

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

【C言語】ポインタの使い方を解説この記事では、C言語のポインタについて解説します。ポインタは、コンピュータのメモリにアクセスするための機能です。ポインタからアドレス先の値にアクセスすることができます。それでは、ポインタの使い方を見ていきましょう!...

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

関数内で値を変更できる

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

関数呼び出しの高速化

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

定義

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

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

呼び出し

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

関数名(&変数);

サンプル

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

#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

構造体の配列

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

【C言語】同じ型の要素をまとめて管理する方法【配列の使い方】この記事では、C言語の配列(array)について解説します。配列とは、1つの変数で同じ型の値をいくつも管理するための機能 です。同じ目的で扱う値が複数存在している場合、配列にまとめることで管理や処理が楽になります。また、配列は for文 と組み合わせることで強力に扱うことができます。それでは、C言語の配列の使い方を見ていきましょう!...

宣言

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

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

初期化

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

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

メンバにアクセス

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

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

サンプル

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

#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言語の関数の使い方を見ていきましょう!...

C言語でデータをまとめて扱いたい場合、「配列」か「構造体」を使います。

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

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

ゆうまる

独学でプログラミングを勉強しているおじさん。いろんな言語を勉強したが浅く広くなためあまり仕事につながらない。また忘れっぽいため自分のブログを備忘録としても使っている。産まれてこのかたずっとネコを飼ってる生粋のネコ派。最近お腹が出てきて筋トレに奮闘中!

View Comments

Recent Posts

【Dart】コンストラクタのデフォルト引数について

Dartのコンストラクタのデフォルト引数…

2週間 ago

【Unity】有料アセットを無料で手に入れる方法

この記事では、Unityの有料アセットを…

4か月 ago

【Python】任意の秒数だけ処理を一時停止する方法【sleep()関数】

この記事では、Pythonで任意の秒数だ…

1年 ago

【Python】Wordの文書の新規作成と読み書き

この記事では、Pythonを使ってWor…

1年 ago

【Python】メタクラスって結局なんなの?

この記事では、Pythonのメタクラスに…

1年 ago