
C言語基礎|構造体の基礎
「バラバラの情報を、ひとつの“まとまり”に。Cの構造体でデータ設計が一気にラクになる!」
C言語でプログラムを書いていると、関連する情報をセットで扱いたい場面がよく出てきます。
たとえば「商品」なら、商品名・価格・在庫数…みたいに、1つの対象に複数の項目がぶら下がるんですよね。
もし構造体が無いと、商品名は配列、価格は別の変数、在庫数も別の変数…と散らばってしまって、
「この3つって同じ商品だっけ?」が分かりにくくなります。
そこで登場するのが 構造体(structure)。
“関連データをひとまとめにして、1つの型として扱える”のが、構造体のいちばん大事な価値です。

構造体って何?(カード形式のイメージ)
構造体は、「項目がそろったカードのフォーマット」を作る感覚に近いです。
図:構造体は「フォーマット」/変数は「実体」
(1) フォーマット(型)
struct Product {
name
price
stock
};
(2) 実体(変数)
struct Product apple;
struct Product banana;
- 上は「こういう項目を持つデータの形」を定義しているだけ(まだ中身は無い)
- 下で初めて「その形を持つデータ(変数)」が作られる
用語の整理(タグ・メンバ・オブジェクト)
まずは言葉をスッキリさせましょう。
| 用語 | 何を指す? | 例 |
|---|---|---|
| 構造体タグ(tag) | struct の後ろに書く名前(型を識別する) | struct Product の Product |
| メンバ(member) | 構造体の中の各項目 | name, price, stock |
| オブジェクト(変数) | 実際に作った“中身を入れられる”実体 | struct Product apple; |
補足(ここ、試験でも混乱しやすい)
- 型名は struct Product(struct とタグ名がセット)
- Product だけは「タグ名」であって、単体では型名ではありません(typedef を使うと話が変わりますが、今は基本だけでOKです)
構造体の宣言(型の作り方)
書式(型を作る)
struct タグ名 {
型 メンバ名;
型 メンバ名;
...
};
この宣言は何をするの?
- { } の中に並んだメンバをまとめて
struct タグ名 という新しい型を作ります。 - 末尾の ; は必須です(ここ、うっかりミス多いです)
オブジェクト(変数)の宣言・定義
書式(実体を作る)
struct タグ名 変数名;
これは何をするの?
- その型(struct タグ名)を持つ 変数(オブジェクト) を作ります。
- 変数なので、あとから値を入れたり、取り出したりできます。
型とオブジェクトを一度に定義する
書式(型定義 + 変数定義をまとめて)
struct タグ名 {
...
} a, b;
これは何をするの?
- 型を定義すると同時に、その型の変数 a と b も作ります。
タグ名を省略する形もある(注意点あり)
struct {
...
} a, b;
- この場合、型に名前が付かないので、別の場所で同じ型の変数を追加定義できなくなります
- 「その場限りの型」でOKなときだけ使うのが安全です
メンバアクセス(ドット演算子)
構造体の中身(メンバ)に触るには ドット演算子 を使います。
| 表記 | 意味 |
|---|---|
| obj.mem | 構造体変数 obj のメンバ mem を表す |
書式
オブジェクト名.メンバ名
例
apple.price
これは「価格」という double型の値そのものを表すので、普通の変数と同じように代入・参照できます。
サンプルプログラム(代入して表示する例)
※元の “学生/身体検査” とは別の、よりシンプルな例に置き換えています。表示メッセージも別の日本語にしています。
プロジェクト名:chap12-2-1 ソースファイル名:chap12-2-1.c
#include <stdio.h>
#include <string.h>
#define NAME_LEN 32
// 商品を表す構造体
struct Product {
char name[NAME_LEN]; // 商品名
int stock; // 在庫数
double price; // 価格
};
int main(void)
{
struct Product item;
strcpy(item.name, "りんご");
item.stock = 12;
item.price = 158.0;
printf("商品名:%s\n", item.name);
printf("在庫:%d 個\n", item.stock);
printf("価格:%.0f 円\n", item.price);
return 0;
}このプログラムで出てくる「命令(要素)」の役割
| 要素 | 何をする? |
|---|---|
| #include <stdio.h> | printf を使えるようにする |
| #include <string.h> | strcpy を使えるようにする |
| #define NAME_LEN 32 | 配列サイズの定数を用意する(変更に強い) |
| struct Product { ... }; | 商品の“型”を作る |
| struct Product item; | その型の変数 item を作る |
| strcpy(item.name, "りんご"); | 文字列を char配列にコピーする(代入はできないため) |
| item.stock = 12; | intメンバへ代入 |
| item.price = 158.0; | doubleメンバへ代入 |
| printf(...) | 画面に表示する |
メンバの初期化(作るときにまとめて入れる)
構造体も、変数を作るときに初期化できます。
配列と似ていて、{ } に 宣言順で 値を並べます。
サンプルプログラム(初期化子の例:一部省略すると 0 になる)
プロジェクト名:chap12-2-2 ソースファイル名:chap12-2-2.c
#include <stdio.h>
#define NAME_LEN 32
struct Product {
char name[NAME_LEN];
int stock;
double price;
};
int main(void)
{
// price を書いていない → 自動的に 0.0 になる
struct Product item = {"みかん", 30};
printf("商品名:%s\n", item.name);
printf("在庫:%d 個\n", item.stock);
printf("価格:%.1f 円\n", item.price);
return 0;
}初期化子のルールまとめ
| ルール | 内容 |
|---|---|
| 並べる順番 | メンバの宣言順(name → stock → price) |
| 書き方 | { 値, 値, 値 } |
| 省略したメンバ | 0(数値なら 0、double なら 0.0、配列は要素が 0 で埋まる) |
| 最後にカンマ | 付けてもよい(スタイル次第) |
図で理解:構造体メモリ配置のイメージ
構造体のメンバは、基本的に宣言順に並ぶイメージでOKです。
(実際にはアラインメントの都合で“すき間”が入ることがあります)
図:宣言順に並ぶ(イメージ)

図の説明(大事ポイント)
- 先頭のメンバほど小さいアドレスに置かれやすい。
- 末尾のメンバほど大きいアドレスに置かれやすい。
- ただし型によっては、CPUが扱いやすい配置にするために、間に空き領域(パディング)が入ることがある。
演習問題
演習12-1
上の「初期化するプログラム」をもとに、変数 item の各メンバのアドレスを表示するプログラムを作成してください。
表示するのは name, stock, price の3つです。
解答例(そのまま動く版)
プロジェクト名:chap12-2-3 ソースファイル名:chap12-2-3.c
#include <stdio.h>
#define NAME_LEN 32
struct Product {
char name[NAME_LEN];
int stock;
double price;
};
int main(void)
{
struct Product item = {"みかん", 30};
printf("name の先頭アドレス:%p\n", (void*)item.name);
printf("stock のアドレス:%p\n", (void*)&item.stock);
printf("price のアドレス:%p\n", (void*)&item.price);
return 0;
}解説(ここで出てくる命令の意味)
| 要素 | 何をする? |
|---|---|
| &item.stock | stock というメンバのアドレスを取る |
| &item.price | price というメンバのアドレスを取る |
| item.name | name は配列なので、式の中では先頭要素へのポインタのように扱われやすい |
| %p | アドレス表示用の書式指定 |
| (void*) | %p に渡すための型変換(お作法) |
