Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
構造体(struct)
異なる型のデータをひとまとめにして扱うためのデータ構造です。名前・年齢・点数など関連するデータをグループ化することで、プログラムの構造が明確になります。
構文
// 構造体型を定義します。
struct 構造体タグ名 {
型 メンバ名1;
型 メンバ名2;
};
// 構造体変数を宣言します。
struct 構造体タグ名 変数名;
// 宣言と同時に初期化します。
struct 構造体タグ名 変数名 = {値1, 値2};
// メンバへのアクセスです。
変数名.メンバ名 // 変数の場合はドット演算子
ポインタ変数->メンバ名 // ポインタの場合はアロー演算子
// typedef と組み合わせて struct を省略できます。
typedef struct {
型 メンバ名;
} 型名;
構造体操作のまとめ
| 操作 | 構文 | 概要 |
|---|---|---|
| メンバアクセス | 変数.メンバ名 | 構造体変数のメンバに直接アクセスします。 |
| ポインタ経由のアクセス | ポインタ->メンバ名 | 『(*p).メンバ』の省略形です。ポインタで構造体を操作する際に使います。 |
| 初期化子 | {.メンバ名 = 値} | C99以降では指定初期化子(designated initializer)が使えます。 |
| 構造体の代入 | s1 = s2 | 同じ型の構造体同士はコピー代入できます(メンバが全部コピーされます)。 |
| 構造体のサイズ | sizeof(struct タグ名) | 構造体全体のバイト数を返します。パディングが入ることがあります。 |
サンプルコード
#include <stdio.h>
#include <string.h>
// 学生を表す構造体を定義します。
typedef struct {
char name[50];
int age;
double score;
} Student;
// 構造体ポインタを引数に受け取って値を設定する関数です。
void init_student(Student *s, const char *name, int age, double score) {
strncpy(s->name, name, sizeof(s->name) - 1);
s->name[sizeof(s->name) - 1] = '\0';
s->age = age;
s->score = score;
}
// 構造体の内容を表示する関数です(値渡し)。
void print_student(Student s) {
printf("名前: %s, 年齢: %d, 点数: %.1f\n", s.name, s.age, s.score);
}
int main(void) {
// 構造体変数を宣言して初期化します。
Student s1 = {"Taro", 20, 85.5};
print_student(s1); // 『名前: Taro, 年齢: 20, 点数: 85.5』と出力されます。
// ドット演算子でメンバにアクセスします。
s1.score = 90.0;
printf("更新後の点数: %.1f\n", s1.score); // 『90.0』と出力されます。
// ポインタ経由で操作します(アロー演算子を使います)。
Student s2;
Student *p = &s2;
init_student(p, "Hanako", 21, 92.0);
printf("名前: %s\n", p->name); // 『Hanako』と出力されます。
printf("点数: %.1f\n", p->score); // 『92.0』と出力されます。
// 構造体の配列を作ります。
Student class[3] = {
{"Taro", 20, 85.5},
{"Hanako", 21, 92.0},
{"Jiro", 19, 78.0},
};
for (int i = 0; i < 3; i++) {
print_student(class[i]);
}
// サイズを確認します(パディングが入ることがあります)。
printf("Student のサイズ: %zu バイト\n", sizeof(Student));
return 0;
}
概要
構造体を関数に渡すと全メンバがコピーされます。大きな構造体の場合は、コピーを避けるためポインタで渡す方が効率的です。ポインタで構造体を受け取った場合、呼び出し元の構造体が変更されます。変更を望まない場合は引数を『const 構造体型 *』と宣言してください。
構造体のメモリサイズはアライメントの都合でパディングが挿入されることがあるため、単純にメンバサイズの合計にはなりません。正確なサイズは『sizeof』で確認してください。
複数の型でメモリを共有する場合は『union(共用体)』を、型名の別名については『typedef』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。