【C言語入門】構造体の使い方(struct、ポインタ、アロー演算子)

構造体を使って関連する 項目をまとめて扱おう

構造体って使ってますか? C言語では構造体を使って、ある対象に関連する項目をひとまとまりに扱うことができます。

たとえば個人情報データならば、氏名、性別、年齢、住所、職業などが項目になり、それぞれのデータは個人によって変わってきます。構造体を使うとこれらをひとつにまとめて宣言しておいて、それをもとに各個別ごとで入れ物(実体)を作り、その入れ物(実体)に項目(メンバ)ごとのデータを入力していくことができます。

したがって、各個別(実体)ごとにそれぞれの項目(メンバ)ごとの変数を用意する必要がなく手間が省けて便利です。この記事では「構造体とは「構造体の使い方」「ポインタ、アロー演算子の使い方」という基本的な内容から、

  • 実体をコピーする方法について
  • 実体を比較演算する方法について
  • 構造体を配列で扱う方法


など応用的な使い方まで、わかりやすく解説していきます!

構造体とは

構造体とは、ある対象に関連する項目をまとめて1つのかたまりにしたものです。

関連する項目はメンバと呼ばれ、変数や文字列などをメンバとすることができます。ただし関数はメンバとすることはできません。

構造体は実体と呼ばれるオブジェクトを生成して使用します。実体からメンバを呼び出し、値を代入して使用します。

なお、同じように項目をまとめて1つのかたまりにしたものに配列があります。ただし、配列の場合は同じ型のモノしか1つのかたまりにできません。

構造体はint型や文字列など型の違うモノでも1つのかたまりにできます。

構造体の使い方について

構造体の使い方について宣言の方法、初期化の方法の順に説明していきます。

structで宣言する方法

構造体の宣言の方法について説明します。構造体は下記のように宣言します。

構造体名の前に「struct」句を記述し、「;」で区切られたメンバを「{};」ブロックで囲みます。

この場合「struct 構造体名」というデータ型として定義されます。これに加えて「typedef」句を使った宣言の方法も使われます。

この場合「struct 構造体名」というデータ型を「構造体名2」というデータ型に型を付け替えるということになります。

このサンプルコードでは前述の2つの宣言方法で記述しています。「struct person1」型と「person2」型を宣言しています。

なお「typedef」句を使った宣言の場合「person」句を省略することもできます。

初期化の方法について

それでは構造体の実体を定義し初期化する方法について説明します。まず前述の宣言の仕方の違いによって、構造体の実体を生成する記述が違ってきます。

「struct 構造体名」型の場合は、次のように定義します。

「typedef」句を使った「構造体名」型の場合は、次のように定義します。

構造体の初期化について全メンバへの一括代入は実体の宣言時のみ可能です。それ以外は一括代入できませんのでご注意ください。

また構造体のメンバは、実体からドット演算子(.)を使って呼び出します。それではサンプルコードを確認していきます。

実行結果:

このサンプルコードでは構造体を「struct person1」型と「person2」型で宣言しています。「struct person1」型を実体化する際には「struct person1 tanaka」と定義しています。

実体「tanaka」のメンバの初期化は各メンバをひとつずつ初期化しています。「person2」型を実体化する際には「person2 sato」と定義しています。

実体「sato」のメンバの初期化は定義と一緒に全メンバ一括で行っています。定義とは別に実体を一括代入しようとしてもコンパイルエラーとなりますのでご注意ください。

実体の各メンバの代入を一つずつ行うと面倒ですので、一括代入用の関数「init」を記述し使用しています。

ポインタ、アロー演算子の使い方

構造体の実体はポインタを使って扱うと全メンバを含む実体全体を扱うことができて便利です。ポインタを使って実体のアドレスを扱う方法について説明します。

実体のポインタからメンバを呼び出すには、アロー演算子を使用します。「->」記号を使います。

下記のように記述して使用します。

サンプルコードで確認していきましょう。

実行結果:

このサンプルコードでは、構造体の実体「sato」のアドレス先にポインタ「p1」を使用しています。

ポインタ「p1」のメンバ「age」のアドレスにアロー演算子「->」を使ってアクセスし、アドレス先の値を初期化しています。また実体「kato」のアドレス先の値に実体「sato」のアドレス先の値を代入しています。

したがって、実体「kato」のメンバ「age」の値も実体「sato」のメンバ「age」と同じ値となっています。

実体をコピーする方法について

同じ実体を複製コピーして使用したい場合があります。そんな場合はポインタを使ってひとつの実体のアドレス先の値をコピーするのが便利です。

それではサンプルコードで確認していきましょう。

実行結果:

このサンプルコードでは、構造体の実体「sato」のアドレス先の値を実体「sato2」のアドレス先に代入しています。アドレス先の値を代入するだけで、メンバ全体の値がコピーされています。

実体を比較演算する方法について

実体がメンバのバイト単位で同じか否かを比較評価する方法について説明します。サンプルコードで確認していきましょう。

実行結果:

このサンプルコードでは、先ほどアドレス先の値をコピーした例を使って、実体が同じかどうか評価しています。比較評価のために自作の関数「buf_equal」を記述して使用しています。メンバを一つずつバイト単位で比較評価しています。

C言語にはヘッダーファイル「string.h」をインクルードするとmemcmp関数でバイト単位の評価ができますが、構造体の実体を比較する場合不具合が発生する可能性があります。これはパディングが起こる可能性があるからです。

パンディングとは奇数個の要素をもつchar型配列をメンバとしてもつ場合に、処理環境によっては1バイト空領域を追加して偶数個に揃える処理のことです。これによりあるメンバのアドレス先からズレが生じることもありますので、memcmp関数を使って評価する場合は注意が必要です。

メンバの値を代入してコピーをするとこのパンディングによるアドレス先のズレが生じることもあります。実体をコピーする場合には先の例のように実体全体のアドレス先の値をコピーし、かつ比較評価する場合はメンバ一つずつバイト単位で評価することをおススメします。

構造体を配列で扱う方法

構造体を配列で扱う方法は、変数を配列で扱う場合と変わりません。変数の配列のように以下のように宣言します。

サンプルコードで確認しましょう。

実行結果:

配列の使い方については、こちらで詳しく解説していますので、ぜひ参考にしてください。

【C言語入門】配列の使い方まとめ(初期化、代入、宣言、コピー)
更新日 : 2019年4月22日

構造体を関数の引数で使用する方法について

構造体の実体を関数の引数で使用する方法について説明します。サンプルコードで確認していきましょう。

実行結果:

このサンプルコードではすでに初期化された実体をコピーするための関数「subst」を使用しています。

「subst」関数ではすでに初期化された実体のアドレス先の値を引数で参照渡ししています。main関数ではすでに初期化された実体「sato」を別の実体「p2」のメンバの値で書き換えています。

構造体を関数の引数で使用する方法については、こちらのサイトでも解説していますので、ぜひ参考にしてください。

【C言語入門】関数の作り方、呼び出し方(宣言、引数、戻り値)
更新日 : 2019年4月24日

ポインタについて詳しく知りたい方へ

これまでお伝えしてきたように、構造体の実体はポインタを使って扱うと便利な場合が多いです。ポインタの使い方については、こちらで詳しく解説していますので、ぜひ参考にしてください。

【C言語入門】ポインタのわかりやすい使い方(配列、関数、構造体)
更新日 : 2019年4月23日

まとめ

ここでは、構造体の使い方について説明しました。構造体を使うと関連する項目をひとまとまりに扱うことができて便利です。

また構造体のメンバ全体をまとめて扱う場合はポインタを使うと、実体のアドレス先の情報ひとつで操作することができて簡単です。

使いこなすことができるように、この記事を何度も参考にして下さいね!

LINEで送る
Pocket

最短でエンジニアを目指すなら侍エンジニア塾

cta_under_bnr

侍エンジニア塾は業界で初めてマンツーマンレッスンを始めたプログラミングスクールです。これまでの指導実績は16,000名を超え、未経験から数多くのエンジニアを輩出しています。

あなたの目的に合わせてカリキュラムを作成し、現役エンジニア講師が専属であなたの学習をサポートするため効率よく学習を進めることができますよ。

無理な勧誘などは一切ありません。まずは無料体験レッスンを受講ください。

無料体験レッスンの詳細はこちら

書いた人

長野 透

長野 透

熊本在住のフリープログラマ兼ライターです。C/C++/C#、Java、Python、HTML/CSS、PHPを使ってプログラミングをしています。専門は画像処理で最近は機械学習、ディープラーニングにはまっています。幅広くやってきた経験を活かしてポイントをわかりやすくお伝えしようと思います。
お問合せはこちらでも受け付けています。
[email protected]

おすすめコンテンツ

あなたにぴったりなプログラミング学習プランを無料で診断!

プログラミング学習の効率を劇的に上げる学習メソッドを解説