C言語構造体:複雑なデータを効率的に整理
構造体とは
配列では同じ種類のデータ項目を複数保持する型の変数を定義できます。同様に構造体は、異なる種類のデータ項目を組み合わせることを可能にするC言語で利用可能なもう1つのユーザー定義データ型です。
構造体はレコードを表すために使用されます。例えば図書館の本を管理したい場合、各本について以下の属性を追跡したいかもしれません:
- タイトル
- 著者
- 主題
- 書籍ID
構造体の定義
構造体を定義するには、struct文を使用する必要があります。struct文は複数のメンバを持つ新しいデータ型を定義します。struct文の形式:
struct [structure_tag] {
member_definition;
member_definition;
...
member_definition;
} [one_or_more_structure_variables];
構造体タグはオプションで、各メンバ定義は通常の変数定義(int i;、float f;、またはその他の有効な変数定義)です。構造体定義の末尾、最後のセミコロンの前に、1つ以上の構造体変数を指定できますが、これはオプションです。Book構造体を宣言する方法:
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
} book;
構造体メンバへのアクセス
構造体の任意のメンバにアクセスするには、メンバアクセス演算子 (.)を使用します。メンバアクセス演算子は、構造体変数名とアクセスしたい構造体メンバの間にピリオドを置いて記述します。構造体型の変数を定義するにはstructキーワードを使用します。以下の例はプログラムでの構造体使用方法を示します:
Live Demo#include <stdio.h>
#include <string.h>
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
};
int main() {
struct Books Book1; /* Book1をBook型で宣言 */
struct Books Book2; /* Book2をBook型で宣言 */
/* 書籍1の仕様 */
strcpy(Book1.title, "C Programming");
strcpy(Book1.author, "Nuha Ali");
strcpy(Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* 書籍2の仕様 */
strcpy(Book2.title, "Telecom Billing");
strcpy(Book2.author, "Zara Ali");
strcpy(Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* 書籍1の情報出力 */
printf("Book 1 title : %s\n", Book1.title);
printf("Book 1 author : %s\n", Book1.author);
printf("Book 1 subject : %s\n", Book1.subject);
printf("Book 1 book_id : %d\n", Book1.book_id);
/* 書籍2の情報出力 */
printf("Book 2 title : %s\n", Book2.title);
printf("Book 2 author : %s\n", Book2.author);
printf("Book 2 subject : %s\n", Book2.subject);
printf("Book 2 book_id : %d\n", Book2.book_id);
return 0;
}
実行結果:
Book 1 title : C Programming Book 1 author : Nuha Ali Book 1 subject : C Programming Tutorial Book 1 book_id : 6495407 Book 2 title : Telecom Billing Book 2 author : Zara Ali Book 2 subject : Telecom Billing Tutorial Book 2 book_id : 6495700
構造体を関数引数として渡す
構造体を関数引数として渡すことは、他の変数やポインタを渡すのと同じ方法で可能です。
Live Demo#include <stdio.h>
#include <string.h>
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
};
/* 関数宣言 */
void printBook(struct Books book);
int main() {
struct Books Book1;
struct Books Book2;
/* 書籍1の仕様 */
strcpy(Book1.title, "C Programming");
strcpy(Book1.author, "Nuha Ali");
strcpy(Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* 書籍2の仕様 */
strcpy(Book2.title, "Telecom Billing");
strcpy(Book2.author, "Zara Ali");
strcpy(Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* 書籍1の情報出力 */
printBook(Book1);
/* 書籍2の情報出力 */
printBook(Book2);
return 0;
}
void printBook(struct Books book) {
printf("Book title : %s\n", book.title);
printf("Book author : %s\n", book.author);
printf("Book subject : %s\n", book.subject);
printf("Book book_id : %d\n", book.book_id);
}
実行結果:
Book title : C Programming Book author : Nuha Ali Book subject : C Programming Tutorial Book book_id : 6495407 Book title : Telecom Billing Book author : Zara Ali Book subject : Telecom Billing Tutorial Book book_id : 6495700
構造体へのポインタ
構造体へのポインタは、他の変数へのポインタを定義するのと同じ方法で定義できます:
struct Books *struct_pointer;
これで、上記で定義したポインタ変数に構造体変数のアドレスを格納できます。構造体変数のアドレスを求めるには、構造体名の前に'&'演算子を置きます:
struct_pointer = &Book1;
その構造体へのポインタを使用して構造体のメンバにアクセスするには、->演算子を使用します:
struct_pointer->title;
上記例を構造体ポインタを使って書き直します。
Live Demo#include <stdio.h>
#include <string.h>
struct Books {
char title[50];
char author[50];
char subject[100];
int book_id;
};
/* 関数宣言 */
void printBook(struct Books *book);
int main() {
struct Books Book1;
struct Books Book2;
/* 書籍1の仕様 */
strcpy(Book1.title, "C Programming");
strcpy(Book1.author, "Nuha Ali");
strcpy(Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* 書籍2の仕様 */
strcpy(Book2.title, "Telecom Billing");
strcpy(Book2.author, "Zara Ali");
strcpy(Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* Book1のアドレスを渡して情報出力 */
printBook(&Book1);
/* Book2のアドレスを渡して情報出力 */
printBook(&Book2);
return 0;
}
void printBook(struct Books *book) {
printf("Book title : %s\n", book->title);
printf("Book author : %s\n", book->author);
printf("Book subject : %s\n", book->subject);
printf("Book book_id : %d\n", book->book_id);
}
実行結果:
Book title : C Programming Book author : Nuha Ali Book subject : C Programming Tutorial Book book_id : 6495407 Book title : Telecom Billing Book author : Zara Ali Book subject : Telecom Billing Tutorial Book book_id : 6495700
ビットフィールド
ビットフィールドを使用すると、構造体内でデータをパックできます。これはメモリやデータストレージが貴重な場合に特に有用です。典型的な例:
- 複数のオブジェクトをマシンワードにパック。例:1ビットフラグをコンパクト化。
- 外部ファイル形式の読み取り - 標準でないファイル形式を読み込み可能。例:9ビット整数。
Cでは、変数の後に:ビット長を置くことで構造体定義内でこれを実現できます。例:
struct packed_struct {
unsigned int f1:1;
unsigned int f2:1;
unsigned int f3:1;
unsigned int f4:1;
unsigned int type:4;
unsigned int my_int:9;
} pack;
ここではpacked_structは6つのメンバを含みます:4つの1ビットフラグf1..f3、4ビットのtype、9ビットのmy_int。
フィールドの最大長がコンピュータの整数ワード長以下であれば、Cは上記ビットフィールドを可能な限りコンパクトに自動的にパックします。そうでない場合、一部のコンパイラではフィールドのメモリオーバーラップを許可し、他では次のフィールドを次のワードに格納します。
C言語
- 次世代磁気ナノ構造「透明マント」でデータストレージを革新
- 2021年 コーディングスキルを飛躍させる厳選17冊のプログラミング本
- 3Dプリント格子構造で部品性能を向上:軽量化・高強度・衝撃吸収を実現
- C++構造体とクラス:組み込み開発者のための実践ガイド
- Nucleus RTOSのセマフォ:ユーティリティサービスとデータ構造
- 書評:『Digitise or Die』——IoT駆動トランスフォーメーションの青写真
- 破壊的テクノロジー時代に人間らしさを保つには
- C言語typedef:カスタム型名でコードをシンプルに
- C++データ構造:配列、構造体、ポインタで効率的なプログラムを構築
- C#の構造体:値型の定義と活用を徹底解説
- Javaデータ構造: 従来クラス(Vector/Stack/Hashtable等)とコレクションフレームワーク概要