はじめに
C言語のプログラムがある程度複雑になってくると、1つの概念を複数の変数で表すことが多くなります。変数が多くなるとついつい可読性が悪く、扱いにくいプログラムとなってしまいます。そこで、便利なのが、構造体という概念です。
そこでここでは以下を解説します。
- 構造体の概念
- 構造体配列
- 構造体のポインタ
構造体
構造体とは、複数の変数をひとまとめにするものです。
構造体テンプレートの定義
以下のような構造体の定義を「構造体テンプレート」と呼びます。
例えば、「生徒」を定義したいとして、持っているパラメータは、以下だとしたい場合を例にしてみましょう。
- 学生番号
- 名前
- 年齢
C言語では以下のように表現します。
struct student {
int id; // 学生番号
char name[256]; // 名前
int age; // 年齢
};
struct student data;
で構造体の変数を定義します。
例えば、data.id = 1;
でdataという構造体のidという変数に1を代入します。という意味です。
このidのことをメンバと呼びます。
コード例1:全文
#include <stdio.h>
#include <string.h>
// 学生のデータを入れる構造体
struct student {
int id; // 学生番号
char name[256]; // 名前
int age; // 年齢
};
int main(int argc, char** argv) {
// 構造体変数の宣言
struct student data;
// メンバに値を代入
data.id = 1; // 学生番号:1
strcpy(data.name, "山田太郎"); // 名前:山田太郎
data.age = 18; // 年齢:18
// データの内訳を表示
printf("学生番号:%d 名前:%s 年齢:%d¥n"
, data.id, data.name, data.age);
return 0;
}
構造体配列
構造体を扱う場合は、配列を用いる場面がほとんどです。
配列に関しては、以下の記事を参考にしてみてください。
コード例2:全文
#include <stdio.h>
#include <string.h>
// 学生のデータを入れる構造体
struct student {
int id; // 学生番号
char name[256]; // 名前
int age; // 年齢
};
// 構造体の名前をtypedefで定義
typedef struct student student_data;
int main(int argc, char** argv) {
int i;
student_data data[] = {
{ 1,"佐藤",21 },
{ 2,"西田",39 },
{ 3,"丸",18 },
{ 4,"石川",48 }
};
// データの内訳を表示
for (i = 0; i < 4; i++) {
printf("学生番号:%d 名前:%s 年齢:%d¥n"
, data[i].id, data[i].name, data[i].age);
}
return 0;
}
実行結果
学生番号:1 名前:佐藤 年齢:21
学生番号:2 名前:西田 年齢:39
学生番号:3 名前:丸 年齢:18
学生番号:14名前:石川 年齢:48
解説
typedefとstruct
typedefとは、既存の型に新しい名前をつけるためのキーワードです。例2ですと、student という名前をstudent_dataという名前に変更しますという意味です。再定義した構造体のデータの定義では、structキーワードが不要となります。
student_data data[]
によって、dataという配列に変数を当てはめることを意味します。
dataの中身は、以下のようになっています。
- data[0]:{ 1,”佐藤”,21 },
- data[1]:{ 2,”西田”,39 },
- data[2]:{ 3,”丸”,18 },
- data[3]:{ 4,”石川”,48 }
構造体のポインタ
コード例2をポインタを使った処理に書き換えます。
コード例3:全文
#include <stdio.h>
#include <string.h>
// 学生のデータを入れる構造体
typedef struct {
int id; // 学生番号
char name[256]; // 名前
int age; // 年齢
}student_data;
// 構造体のデータを表示する関数
void setData(student_data*, int, char*, int);
void showData(student_data*);
int main(int argc, char** argv) {
student_data data[4];
int i;
int id[] = { 1,2,3,4 };
char name[][256] = { "佐藤","西田","丸","石川" };
int age[] = { 21,39,18,48 };
// データの設定
for (i = 0; i < 4; i++) {
setData(&data[i], id[i], name[i], age[i]);
}
// データの内訳を表示
for (i = 0; i < 4; i++) {
showData(&data[i]);
}
return 0;
}
// データのセット
void setData(student_data* pData, int id, char* name, int age) {
pData->id = id; // idのコピー
strcpy(pData->name, name); // 名前のコピー
pData->age = age; // 年齢のコピー
}
// データの表示
void showData(student_data* pData) {
printf("学生番号:%d 名前:%s 年齢:%d¥n"
, pData->id, pData->name, pData->age);
}
解説
以下の表記で、構造体テンプレートと名前の変更が一括で可能です。
typedef struct {
int id; // 学生番号
char name[256]; // 名前
int age; // 年齢
}student_data;
アロー演算子
通常の構造体のメンバへのアクセスは「.」で行います。一方でポインタ変数の場合は、「->」で行います。「->」をアロー演算子と呼びます。
setData関数とshowData関数では、ポインタ形式でデータを渡しています。
setData関数は、student_dataの構造体のアドレスをポインタpDataに代入し、pDataのメンバにid,name,ageをそれぞれコピーしています。
値を渡すときは、ポインタで渡すことが大切(一般的)です。
ポインタで渡す理由としては、構造体で値を渡すときに無駄にスタック領域を圧迫しないためです。
値で渡すと別のアドレスに格納されてしまうため、無駄にリソースを使用してしまうためです。
まとめ
今回は、C言語の構造体について解説しました。構造体とは、複数の変数をひとまとめにするものです。配列やポインタを使って構造体に値を与えます。構造体の値を渡すときには、ポインタで渡すことが大切です。なぜなら、無駄にリソースを使用しないためです。
もっと詳しくC言語を学習したい方は以下の記事を参考にしてみてください。オンライン学習サイトUdemyのおすすめ講座についてまとめたものです。
筆者がC言語の学習は以下の本がおすすめです。参考にしてみてください。
コメント