この記事では、C言語の構造体について解説します。
構造体を使うことで異なる型の変数を一つの型にまとめて管理することができます。
それでは、C言語の構造体の使い方を見ていきましょう!
構造体は、structキーワードを使って以下のように定義します。
struct 構造体タグ名 { 型 メンバ1; 型 メンバ2; ・ ・ ・ };
;」を忘れないように!宣言
構造体を使用するには、構造体の型の変数を宣言する必要があります。
struct 構造体タグ名 変数名;
構造体の型の変数は、構造体変数と呼ばれたりする
初期化
構造体を初期化するには、メンバの数だけデータを渡します。
struct 構造体タグ名 変数名 = {データ1, データ2, ... データN};
メンバにアクセス
メンバにアクセスするには、. で構造体変数名とメンバ名をつないでアクセスします。
構造体変数名.メンバ名;
サンプル
構造体を定義して使ってみましょう。
#include <stdio.h> struct person { char *name; // 名前 int age; // 年齢 }; int main(void) { // 宣言 struct person mike; // 以下のように宣言・初期化できます。 // struct person mike = {"Mike", 24}; // メンバを1つずつ初期化 mike.name = "Mike"; mike.age = 24; // 出力 printf("名前: %s, 年齢: %d\n", mike.name, mike.age); }
実行結果
名前: Mike, 年齢: 24
typedefキーワード を使うことで、構造体宣言時に struct を省略できます。
構造体定義後に typedef で新しい名前を付けることで struct を省略できます。
typedef struct 構造体タグ名 付ける名前;
サンプル
以下のコードでは、構造体personを struct 無しで宣言できるようにしています。
struct person { char *name; // 名前 int age; // 年齢 }; // 新しい名前を付ける(タグ名と同じでも問題ない) typedef struct person person; int main(void) { // struct無しで宣言できる person mike; }
typedef を使って構造体を定義することで struct を省略して宣言できます。以下のように定義することができます。
typedef struct 構造体タグ名 { 型 メンバ1 型 メンバ2 ・ ・ ・ } 付ける名前;
サンプル
構造体person を typedef を使いながら定義しています。
// typedefを使いながら構造体定義 typedef struct person { char *name; // 名前 int age; // 年齢 } person; int main(void) { // struct無しで宣言 person mike; }
typedef を使いながら構造体を定義する際に、構造体タグ名を省略することができます。この方法が一番簡潔に構造体を使えます。
定義
構造体タグ名を省略して定義します。
typedef struct { 型 メンバ1; 型 メンバ2; ・ ・ ・ } 付ける名前;
サンプル
構造体person を書き直してみます。
typedef struct { char *name; // 名前 int age; // 年齢 } person; int main(void) { // 宣言 person mike; }
構造体を関数の引数や戻り値に使うことで、複数の値を受け渡しすることができます。
以下のコードでは、引数に構造体を受け取る関数を定義し、呼び出しています。
#include <stdio.h> typedef struct { char *name; // 名前 int age; // 年齢 } person; // 引数にpersonを受け取る関数 void print(person p){ printf("名前: %s, 年齢: %d\n", p.name, p.age); } int main(void) { // 宣言・初期化 person mike = {"Mike", 24}; // 引数にperson型の変数を渡す print(mike); }
実行結果
名前: Mike, 年齢: 24
構造体はポインタとして扱うこともできます。ポインタの宣言方法は通常の変数となんら変わりません。
構造体はポインタ引数を使うことで、以下のようなメリットがあります。
関数内で値を変更できる
戻り値以外にも外部に影響を及ぼすことができる。
関数呼び出しの高速化
構造体は値渡しなので全ての値をコピーして関数に渡します。メンバが1つ2つなら問題ありませんが、大きな構造体の場合はコピーに時間がかかります。その点、ポインタを使う場合では、構造体の先頭のアドレスを渡すだけで良いので高速処理が可能です。
定義
通常のポインタ引数と変わりません。
型名 関数名(型名 *ポインタ){ // メンバにアクセス ポインタ->メンバ名; }
呼び出し
&を使ってアドレスを渡します。
関数名(&変数);
サンプル
構造体をポインタ引数に渡して処理してみましょう!
#include <stdio.h> typedef struct { char *name; int age; } person; void print(person *p){ printf("名前: %s, 年齢: %d\n", p->name, p->age); } int main(void) { // 宣言・初期化 person mike = {"Mike", 24}; print(&mike); }
実行結果
名前: Mike, 年齢: 24
構造体も配列を使って宣言することができます。
宣言
struct を記述する以外に他の型との違いはありません。
struct 構造体タグ名 変数名[要素数];
初期化
以下のように初期化します。
struct 構造体タグ名 変数名[要素数] = { {データ1-1, データ1-2, ..., データ1-N}, {データ2-1, データ2-2, ..., データ2-N}, ・ ・ ・ };
メンバにアクセス
メンバにアクセスするには、以下のようにします。
構造体変数名[インデックス].メンバ名;
サンプル
構造体の配列を宣言・初期化・出力してみましょう。
#include <stdio.h> typedef struct { char *name; int age; } person; void print(person p[], int length){ for(int i = 0; i < length; ++i){ printf("名前: %s, 年齢: %d\n", p[i].name, p[i].age); } } int main(void) { // 構造体の配列の宣言・初期化 person persons[] = { {"Mike", 24}, {"Sam", 18}, {"Jason", 56} }; // personsの長さ int length = sizeof(persons) / sizeof(persons[0]); print(persons, length); }
実行結果
名前: Mike, 年齢: 24 名前: Sam, 年齢: 18 名前: Jason, 年齢: 56
この記事では、C言語の構造体について解説しました。
以下のコードで今回の内容をおさらいしてみてください。よくわからない箇所があったら記事を読み返してみましょう!
#include <stdio.h> // personを出力するだけの関数形式マクロ #define print(p) printf("name: %s, age: %d\n", p.name, p.age) // 構造体定義 typedef struct { char* name; int age; } person; // 誕生日の関数 void birthday(person* p){ p->age++; } int main(void){ // 構造体の初期化 person mike = {"Mike", 24}; print(mike); birthday(&mike); print(mike); return 0; }
実行結果
name: Mike, age: 24 name: Mike, age: 25
関数や関数形式マクロについては以下を参照してください。
C言語でデータをまとめて扱いたい場合、「配列」か「構造体」を使います。
配列は同じ型の要素しか格納できないので異なる型を扱いたい場合は、構造体を使ってデータをまとめましょう。さらに、構造体の配列を使うことで複雑なデータを扱うことができます。
それでは今回の内容はここまでです!ではまたどこかで〜( ・∀・)ノ
View Comments