
C言語基礎|12章のまとめ
「構造体が分かると、C言語が“現実の形”で書ける。12章で身につけた設計力を総整理!」
12章では、構造体を通して「データをどうまとめるか」「どう扱うか」を、かなり実戦的に学びました。
ただ文法を覚えるだけじゃなくて、現実世界のまとまりを、プログラムに素直に投影するという考え方が身についたはずです。
このまとめでは、12章で登場した重要ポイントを、表や図で整理しながら「なぜそうなるのか」までしっかり確認します。
最後に、まとめ用のサンプルも“別のシンプル例”に差し替えて、もう一度スッキリ復習できるようにしますね。

12章で押さえた「派生型」5種類
基本型(int や double など)を素材にして、C言語は色々な型を組み立てられます。これが派生型です。
派生型の種類と代表的な書式
| 派生型 | 代表的な書式 | 何を表す? |
|---|---|---|
| 配列型 | Type a1[n]; | 同じ型の要素が並ぶ集合 |
| 構造体型 | struct { Type m1; Type m2; } a2; | 異なる型をひとまとめにする集合 |
| 共用体型 | union { Type m1; Type m2; } a3; | 同じ領域を共有してメンバを切り替える |
| 関数型 | Type a4(Type p1, Type p2) { ... } | 引数と戻り値で決まる型 |
| ポインタ型 | Type *a5; | どこかのオブジェクトや関数を指す型 |
図:派生型は「素材から組み立てる」

図の説明
C言語は「型を組み合わせて設計する」言語です。構造体はその中心的な道具でした。
現実世界を投影するときのコツは「まとまりのまま」
現実のモノはたいてい、情報がセットです。
それをバラすと、管理が難しくなりがちです。
投影の方針
| 方針 | 例 | うれしさ |
|---|---|---|
| まとまりを保つ | 人(名前・誕生日)を1つの構造体にする | 関連が壊れにくい、読みやすい |
| ばらばらにする | 名前配列と誕生日配列を別々にする | ズレやすい、修正がつらい |
メンバと構成メンバ(入れ子の見方)
構造体の中には、基本型だけでなく配列や構造体を置けます。
このとき、分解して見たくなるのが「構成メンバ」です。
図:メンバと構成メンバの違い(イメージ)

呼び方の整理
| 用語 | 意味 |
|---|---|
| メンバ | 構造体の直下に並ぶ部品 |
| 構成メンバ | それ以上分解できない最小単位の部品 |
記憶域への並びは「宣言順」
構造体のメンバは、基本的に宣言した順番でメモリに並びます(細部はアライメントの影響あり)。
図:宣言順に並ぶ(イメージ)

図の説明
構造体は「カードのフォーマット」のようなもので、項目(メンバ)が宣言順に配置されます。
タグ名と typedef 名の違い
構造体の型名は、タグ名の有無や typedef によって変わります。ここは混乱しやすいので表で整理します。
タグ名と typedef の関係
| 宣言 | 型名として使える呼び方 | 特徴 |
|---|---|---|
| struct student { ... }; | struct student | タグ名を使う、2単語 |
| typedef struct student { ... } Student; | struct student と Student | 同義語を追加できる |
| typedef struct { ... } Student; | Student | タグがないので struct student は使えない |
初期化子のルール(省略は0になる)
構造体の初期化は、メンバの順に値を並べて {} で囲みます。
書式
型名 変数 = { 初期化子1, 初期化子2, ... };
初期化のポイント
| ルール | 内容 |
|---|---|
| メンバ順 | 宣言順に対応 |
| 省略 | 省略されたメンバは 0 で初期化 |
| 最後のカンマ | 付けてもよい(読みやすさに便利) |
メンバアクセス演算子 . と ->
構造体を扱うときの最重要アイテムです。
. と -> の使い分け
| 対象 | 記法 | 例 |
|---|---|---|
| 構造体変数 | . | obj.mem |
| 構造体へのポインタ | -> | p->mem |
| ポインタで . を使う場合 | (*p).mem | (*p).mem(括弧が必要) |
p->mem は (*p).mem の短縮
p -> mem ≒ (*p).mem
図の説明
-> は「ポインタが指す構造体のメンバへアクセス」を短く書くための演算子です。
配列と構造体は「集成体型」
複数データの集まりという意味で、配列と構造体は仲間扱いされます。
集成体型の共通点と違い
| 観点 | 配列 | 構造体 |
|---|---|---|
| 集まり | 同じ型の集合 | 異なる型の集合が得意 |
| 添字アクセス | できる | できない(メンバ名でアクセス) |
| 代入 | できない | 同じ型ならできる |
構造体は代入できる(ここが強い)
構造体同士の代入は「全メンバをまとめてコピー」です。
構造体代入のイメージ

説明
個別に name だけ、birthday だけ…とコピーを書く必要が減るので、実務でもミスが減ります。
関数は配列を返せないが、構造体は返せる
配列は代入できないので、戻り値として返す形が作れません。
構造体は代入できるので戻り値にできます。
戻り値にできる?
| 種類 | 関数の戻り値 | 理由 |
|---|---|---|
| 配列 | そのままは不可 | 代入できないため |
| 構造体 | 可能 | 値として返して代入できるため |
名前空間は4種類(同名でも衝突しないことがある)
Cには「同じ綴りでも役割が違えばOK」という仕組みがあります。
名前空間の4分類
| 名前空間 | 例 | どこで使う? |
|---|---|---|
| ラベル名 | start: | goto の飛び先 |
| タグ名 | struct X | struct/union/enum のタグ |
| メンバ名 | obj.x | 構造体の中 |
| 一般的な識別子 | 変数名/関数名 | ふだんの名前 |
まとめ用サンプル
社員名簿(社員と入社日)を構造体で表現するプログラム例です。
仕様
- Date 構造体(年・月・日)
- Employee 構造体(名前・入社日 Date)
- 今日の日付を入力して表示
- 社員一覧を -> で表示(ポインタ引数)
プロジェクト名:chap12-10-1 ソースファイル名:chap12-10-1.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
#define NAME_LEN 64
struct Date {
int y;
int m;
int d;
};
typedef struct {
char name[NAME_LEN];
struct Date joined;
} Employee;
void print_Employee(const Employee *e)
{
printf("%s(入社日:%04d/%02d/%02d)\n",
e->name, e->joined.y, e->joined.m, e->joined.d);
}
int main(void)
{
struct Date today;
Employee list[] = {
{"田中", {2021, 4, 1}},
{"鈴木", {2022, 10, 15}},
{"佐藤", {2023, 7, 20}},
};
printf("今日の日付を入力してください。\n");
printf("年:"); scanf("%d", &today.y);
printf("月:"); scanf("%d", &today.m);
printf("日:"); scanf("%d", &today.d);
printf("入力を確認しました:%d年%d月%d日\n", today.y, today.m, today.d);
printf("--- 社員一覧 ---\n");
for (int i = 0; i < (int)(sizeof(list) / sizeof(list[0])); i++) {
print_Employee(&list[i]);
}
return 0;
}サンプル内の命令(要素)の書式と役割
struct Date { ... };
| 要素 | 書式 | 何をする? |
|---|---|---|
| 構造体宣言 | struct タグ名 { ... }; | 型(フォーマット)を作る |
typedef struct { ... } Employee;
| 要素 | 書式 | 何をする? |
|---|---|---|
| typedef | typedef struct { ... } 型名; | 型名を1単語で使えるようにする |
print_Employee(const Employee *e)
| 要素 | 書式 | 何をする? |
|---|---|---|
| ポインタ引数 | const Employee *e | Employee を参照だけする(中身を変えない) |
| -> | e->joined.y | ポインタが指す構造体のメンバにアクセス |
sizeof(list) / sizeof(list[0])
| 要素 | 書式 | 何をする? |
|---|---|---|
| sizeof | sizeof(対象) | 対象のバイト数を得る |
| 要素数 | sizeof(list)/sizeof(list[0]) | 配列の要素数を計算する |
12章のポイントを一枚で整理(チェックリスト)
最終チェック
| 覚えたいこと | ひとことで |
|---|---|
| 構造体は“まとまり” | 現実の形でデータを扱える |
| . と -> | 変数なら .、ポインタなら -> |
| 初期化 {} | メンバ順、省略は0 |
| typedef | 型名を1単語にできる |
| 構造体は代入できる | 全メンバがまとめてコピー |
| 構造体は返せる | 関数の戻り値にできる |
| 配列は返せない | そのままの戻り値は不可 |
| 名前空間 | 役割が違えば同名でもOK |
