【C言語】構造体についてわかりやすく解説します




最近C/C++を勉強し始めているケイタです。仕事ではPHP、趣味ではPythonを使っていたのですが、もう少し低水準の言語も扱いたいというのと、基本情報技術者試験と院試でC言語が重要なので勉強し始めました。

実は、大学生のときに授業でC言語を習ったはずなのですが挫折しました。しかし、PHPやPythonなどの比較的簡単で理解しやすいインタプリタ型言語に慣れてから勉強してみると、色々と発見があって面白かったです。

今回はその中でも特に独特な「構造体」についてまとめてみました。

構造体とは

「構造体」とは、異なる型のデータをまとめて格納することが出来る型のことを指します。

オブジェクト指向でいうオブジェクトのようなものと捉えると分かりやすいかも知れません。PHPやPythonなどの言語では配列で簡単に実装できます。

ではなぜC言語では「構造体」と呼ばれているのかというと、そもそもC言語にはオブジェクト指向がなく、また「配列」とは明確に区別されているからです。

構造体・オブジェクト・配列
  • 構造体…異なる型のデータをまとめて格納することが出来る
  • オブジェクト…異なる型のデータと処理(メソッド)をまとめて格納することができる
  • 配列…同じ型のデータをまとめて格納することが出来る

構造体を使う

では、実際に構造体をコードで書いてみます。今回のサンプルは、学生のデータを構造体で表すものにしてみます。

#include <stdio.h>
#include <string.h>

//①構造体の定義
typedef struct {
    int id;
    char name[255];
    int age;
} student; //型の名前をstudentに設定する

int main() {
    //②student型の変数dataを生成
    student data;
    
    //③dataに値をセット
    data.id = 1;
    strcpy(data.name, "KEITA");
    data.age = 18;
    
    //④画面に標準出力
    printf("ID: %d\nNAME: %s\nAge: %d\n", data.id, data.name, data.age);
}

/* 出力結果
ID: 1
NAME: KEITA
Age: 18
Program ended with exit code: 0
*/

①構造体の定義

まずは、構造体の定義を行います。オブジェクト指向でいうと、メンバ変数の設定と同じです。

[typedef struct { 定義 } 型名 ]を記述することで、定義することが出来ます。ここで言う「型名(=student)」とは、クラス名に対応します。

Cにおいて型名は、intやcharの仲間と思っていただいても構いません。今回は、idとnameとageの3つを設定しました。

②student型の変数dataを作成

そして、早速定義したstudent型を利用して変数dataを作成します。これはオブジェクト指向でクラスからインスタンスを作成することに対応します。

③dataに値をセット

実際の値(id, name, age)を入れる器(=data)が出来たので、実際に入れていきます。

値をセットするときは、他の言語のようにオブジェクトとその中に設定してある変数名をドット(.)でつなぐことで実現できます。

④画面に標準出力

実際にセットされたか画面に表示してチェックしています。

構造体に対してポインターを使う場合

上では、student型の変数dataに値をセットするときに、data.idのようにドット(.)で変数と中身の名前をつなぎました。しかし、ポインターを利用して値をセットする場合はアロー演算子(->)を利用するので注意が必要です。

#include <stdio.h>
#include <string.h>

//①構造体の定義
typedef struct {
    int id;
    char name[255];
    int age;
} student; //型の名前をstudentに設定する

void setData(student*, int, char*, int);

int main() {
    //②student型のデータdataを生成
    student data;
    
    //③student_dataに値をセット
    int id = 1;
    char name[256] = "KEITA";
    int age = 18;
    
    setData(&data, id, name, age);
    
    //④画面に標準出力
    printf("ID: %d\nNAME: %s\nAge: %d\n", data.id, data.name, data.age);
}

//値をセットする関数
void setData(student* pData, int id, char* name, int age) {
    pData->id = id;
    strcpy(pData->name, name);
    pData->age = age;
}

こちらは③が先ほどとは様子が違います。直接dataに対してidやnameをセットするのではなく、dataに対するポインタpDataと、id, name, ageを関数setData()に渡すことで実現しています。

setData()の中身を見るとわかるように、pDataはポインタであるので、pData.idではなくpData->idとアロー演算子で指定しています。

まとめ

構造体は、実際のプログラミングを利用する上で非常に便利なものです。実際、PHPやPythonでも同じようなことをしています。例えばPHPだと配列を使って簡単に実装できるんですよね。

<?php

$data = [
  'id' => 1,
  'name' => 'KEITA',
  'age' => 18
];

?>

いかにスクリプト言語が便利であるかを実感しました。