C言語の構造体とは?使い方の基本から応用まで徹底解説!

プログラミングを行ううちに、同じような情報をひとまとめにできたら便利だと感じることがあると思います。
C言語の構造体は、まさにそんな状況で役立つ仕組み。変数を一つずつ宣言する手間を減らしたり、コードの見通しを良くしたりするのに大いに活躍します。
C言語を学んだばかりでも、使い方を理解しておくと、保守性や可読性が向上するでしょう。
この記事では、構造体の基本的な定義や宣言から、応用的なテクニックまでをサンプルコードとともに解説します。
C言語の構造体とは?
C言語の構造体とは、関連する複数のデータをひとまとめにして扱えるユーザー定義型のことです。
たとえば名前や年齢、座標など異なる型の変数を一つのまとまりとして管理できるため、複雑な情報をシンプルに表現できます。
構造体を理解すると、実世界のオブジェクトをコード上で自然に扱えるようになり、プログラム全体の見通しが良くなるでしょう。
また構造体はメモリ上で連続した領域に配置されるため、ファイル入出力やネットワーク通信でデータを扱いやすくなる点も魅力です。
C言語で構造体を使うメリット
C言語で構造体を使うメリットは、関連するデータを整理してコードの可読性を高められることです。
個別の変数をまとめることで宣言やアクセスが簡潔になり、関数の引数としてまとめて渡せるためインターフェースが明確になります。
構造体単位で扱うので、変更が必要になったとき修正範囲も限定でき、バグの発見や拡張も容易でしょう。
さらに構造体は他の構造体をメンバーに持つネストが可能で、複雑なデータ構造を段階的に設計できます。
結果としてコードの再利用性が高まり、仕様変更時の手間を減らせる点もメリットです。
構造体・クラス・共用体の違い
構造体、クラス、共用体はデータをまとめる点で似ていますが役割が異なります。
構造体はC言語で使い、複数のメンバーを個別に保持する集まりとして機能します。
クラスは主にC++で導入され、構造体の機能に加えてアクセス制御やメソッド、コンストラクタ、継承などのオブジェクト指向機能を備えます。
共用体はメンバーが同じメモリ領域を共有するため、一度に一つの値しか保持できないことから、メモリ効率が重視される場面で有効です。
なお、本記事のここから先は実際のサンプルコードが多く登場します。開発環境の構築から始める方は、ぜひ以下の記事も参考にしてください。
C言語の構造体の使い方【基本】
この章では、C言語の構造体の基本的な使い方を紹介していきます。
手順①:構造体の定義
構造体を定義するには大きく分けて2つの方法があります。
まず
struct 構造体名 { … };
と書いて型だけを定義し、必要に応じて
struct 構造体名 実体名
と宣言して変数を作成します。
もう1つは typedef を使う方法で、
typedef struct { … } 構造体名;
と書けば、以降は「構造体名 実体名;」だけで変数を宣言できます。
どちらも宣言時に {} で全メンバを指定すれば一括初期化が可能ですが、一括代入は宣言時のみ許され、それ以外ではまとめて代入できません。
用途や可読性に合わせて使い分けると良いでしょう。
手順②:構造体変数の宣言
構造体を定義した後は、その型を使って変数を宣言する手順に移ります。
変数宣言では
struct 型名 変数名;
と記述し、同じ構造を持つ複数のインスタンスを簡単に作成できます。
#include <stdio.h>
struct Person {
char name[20];
int age;
};
int main(void) {
struct Person p1, p2;
printf(“Size of Person: %zu bytes\n”, sizeof(p1));
return 0;
}
実行結果:
Size of Person: 24 bytes
このコードでは
struct Person {…}
で Person という構造体型を定義し、
struct Person p1, p2;
で2つの構造体変数を宣言しています。
各変数は name と age のメンバーを独立して保持し、同じ型のインスタンスを複数作成できる点が便利です。
構造体変数は宣言時に自動で初期化されないため、使用前に各メンバーへ値を代入する必要があります。
手順③:構造体のメンバーへアクセス
構造体のメンバーへアクセスするには、ドット演算子(.)を使います。
構造体変数名.メンバー名を記述することで、個々のフィールドに値を代入したり参照したりできます。
初期化時には中括弧( {} )を用いてまとめて指定可能で、メンバーごとの順序を守る必要があります。
また、構造体を関数の引数に渡す際もドット演算子を使って特定のメンバーだけを渡すか、構造体全体をコピー渡しするか選ぶことになります。
#include <stdio.h>
struct Person {
char name[20];
int age;
};
int main(void) {
struct Person p = {“Alice”, 30};
printf(“Name: %s\n”, p.name);
printf(“Age: %d\n”, p.age);
return 0;
}
実行結果:
Name: Alice
Age: 30
上記のコードでは、定義済みの構造体 Person の変数 p を宣言と同時に初期化しています。
{“Alice”, 30}
によって name フィールドに文字列が、age に数値が設定される仕組みです。
構造体のメンバーにアクセスする際はドット演算子(`.`)を使い、p.nameで文字列、p.ageで整数を参照します。printf` 関数では %s と %d を使ってそれぞれ表示し、改行で見やすく出力しています。
構造体の初期化は宣言時のみ可能で、後からまとめて代入することはできませんが、個別のフィールド更新は可能です。
C言語の構造体の使い方【応用】
ここからは、C言語の構造体の応用的な使い方を紹介します。
それぞれサンプルコードと結果を含めてわかりやすく解説しますので、ぜひ参考にしてください。
①:構造体の初期化
構造体の初期化は、宣言時に {} を使って全メンバーに値を一括設定できます。宣言と同時に初期値を指定することで、コードを簡潔にすることが可能になります。
C99以降はメンバー名を指定する「指定初期化」も可能で、順序を気にせず一部だけ設定できます。ただし宣言後にまとめて代入することはできず、個別のフィールド更新はドット演算子を使って行います。
サンプルコードと実行結果
#include <stdio.h>
struct Point { int x; int y; };
int main(void) {
struct Point p1 = {10, 20};
struct Point p2 = {.y = 50, .x = 30};
printf(“p1=(%d, %d)\n”, p1.x, p1.y);
printf(“p2=(%d, %d)\n”, p2.x, p2.y);
return 0;
}
実行結果:
p1=(10, 20)
p2=(30, 50)