はじめに
この記事について
「C言語の基礎を学ぼう」をテーマに、自身の知識 + α をアドベントカレンダーにまとめます。
25日間でC言語をマスターしよう - Qiita Advent Calendar 2025 - Qiita
こんな方を対象としています
-
コンピュータがプログラムをどのように動かしているか知りたい/知らない方
-
プログラミングをしてみたい方
-
C言語初心者の方
キーワード
- 構造体
説明
構造体
複数の変数をひとまとまりに扱いたい場合、 構造体 を利用します。
#include <stdio.h>
#include <string.h> // strcpy()
struct Employee { // 構造体
int id; // メンバ変数
char name[20]; // メンバ変数
};
int main(void) {
// 宣言
struct Employee emp;
// 初期化
emp.id = 123;
strcpy(emp.name, "edamame");
// 表示
printf("id: %d name: %s", emp.id, emp.name);
return 0;
}
id: 123 name: edamame
struct で構造体のメンバを定義します。
定義した構造体は、型のように扱うことができます。
上記の emp.id のように、 . で各メンバにアクセスすることができます。
上記の emp.name はchar配列のため、単純に = で値を代入することができません。
配列の要素を1つずつコピーすることもできますが、今回は string.h の strcpy() を使用しています。
strcpy(コピー先char[], コピー元char[])
また、 enum と同様 typedef を使用することで、変数の宣言を簡単にすることができます。
#include <stdio.h>
#include <string.h>
typedef struct {
int id;
char name[20];
} Employee;
int main(void) {
Employee emp; // structが不要
emp.id = 123;
strcpy(emp.name, "edamame");
printf("id: %d name: %s", emp.id, emp.name);
return 0;
}
id: 123 name: edamame
今回、 . を使用して初期化しましたが、宣言と同時に初期化することも可能です。
#include <stdio.h>
#include <string.h>
typedef struct {
int id;
char name[20];
} Employee;
int main(void) {
Employee emp = {123, "edamame"}; // 初期化
printf("id: %d name: %s", emp.id, emp.name);
return 0;
}
id: 123 name: edamame
構造体のポインタ
構造体を指すポインタを定義することができます。
ポインタからメンバ変数へアクセスする場合、アロー演算子 -> を使用します。
#include <stdio.h>
#include <string.h>
typedef struct {
int id;
char name[20];
} Employee;
int main(void) {
Employee emp = {123, "edamame"};
Employee *emp_p; // ポインタ
emp_p = &emp; // アドレスをコピー
printf("id: %d name: %s", emp_p->id, emp_p->name);
return 0;
}
id: 123 name: edamame
練習
1. コンビニの在庫管理をしよう
- 商品名、価格、在庫数をメンバ変数とした構造体
Productを作成しよう。 -
Productの配列を定義しよう。 - 1つの
Productを初期化するinit_productを作成しよう。 -
Productのメンバ変数を表示するprint_productを作成しよう。
// 引数 : Productのアドレス、商品名、価格、在庫数
init_product(*Product, char[], int, int)
// 引数 : Product
print_product(Product)
Apple : 120円 在庫数 : 55
Banana : 200円 在庫数 : 30
Coffee : 100円 在庫数 : 180
ポイント
init_product は参照渡し、 print_product は値渡しです。
それぞれ適した演算子でメンバ変数にアクセスしましょう。
値渡しの場合、関数内での変更は呼び出し元に影響しません。
(新しいメモリ領域を確保するため)
参照渡しの場合、関数内での変更が呼び出し元に影響します。
(呼び出し元のメモリ領域を操作するため)
通常、構造体は値渡しをすることはあまりなく参照渡しがほとんどです。
今回は値渡しも練習してみます。
解答例
#include <stdio.h>
#include <string.h>
typedef struct {
char name[20];
int price;
int stock;
} Product;
void init_product(Product *product, char* name, int price, int stock);
void print_product(Product product);
int main(void) {
Product items[3];
init_product(&items[0], "Apple", 120, 55);
init_product(&items[1], "Banana", 200, 30);
init_product(&items[2], "Coffee", 100, 180);
print_product(items[0]);
print_product(items[1]);
print_product(items[2]);
return 0;
}
void init_product(Product *product, char* name, int price, int stock) {
strcpy(product->name, name);
product->price = price;
product->stock = stock;
}
void print_product(Product product) {
printf("%s : %d円 在庫数 : %d\n", product.name, product.price, product.stock);
}
Apple : 120円 在庫数 : 55
Banana : 200円 在庫数 : 30
Coffee : 100円 在庫数 : 180
おわりに
構造体を使うことでデータベースのレコードのようなものを表現することができます。
オブジェクト指向言語のクラスにも似ていますね。Javaっぽいな。
参考文献
↓↓↓ はじめてプログラミングを学んだときに読んだ本です ↓↓↓
詳細(プログラミング入門 C言語)|プログラミング|情報|実教出版