構造体の配列は、C言語において同種のデータを保存し処理する一般的な方法の1つであり、データテーブル、点の配列、従業員などの形で使用されます。
問題の歴史:
配列と構造体のサポートは、データを整理するための利便性からC言語の初期バージョンで導入されました。しかし、構造体の配列を扱う際は、言語の特性、メモリの操作、およびデータの受け渡しの原則を理解する必要があります。
問題:
構造体の配列を誤って初期化した場合やメモリの混乱、配列を関数に渡す際の取り扱い(ポインタとして渡されることがある)、また不適切なインデックス付けによる構造体のフィールドへのアクセスエラーが発生します。
解決策:
. および -> を介してアクセスします。コード例:
#include <stdio.h> struct Point { int x; int y; }; void print_points(struct Point *arr, int size) { for(int i = 0; i < size; ++i) { printf("(%d, %d)\n", arr[i].x, arr[i].y); } } int main() { struct Point points[3] = { {1,2}, {3,4}, {5,6} }; print_points(points, 3); return 0; }
主要な特徴:
配列内の構造体のフィールドにアクセスする際、ピリオドと矢印の違いは何ですか?
arr[i].field は arr[i] が構造体そのものである場合に使用します。
ptr->field は ptr が構造体へのポインタである場合に使用します。
struct Point *p = &points[0]; printf("%d", p->x); // 正しい // points[0].x も正しい
部分的な初期化を行った場合、他のフィールドにはどのような値が入りますか?
部分的な初期化では、指定されていないフィールドは静的に割り当てられた配列ではゼロで埋められますが、自動(スタック)変数については初期化なしでゼロにはなりません。
struct Point arr[2] = { {10} }; // arr[0].x = 10, arr[0].y = 0, arr[1].x および arr[1].y = 0
構造体の配列を関数に渡すとき、構造体のコピーが渡されますか?
いえ、最初の要素へのポインタが渡され、関数は元のメモリに対して操作できるため、要素を変更することができます。
プログラマが構造体の配列を宣言し、フィールドを初期化せずに関数に渡して埋め込もうとしました。ポインタ操作時に.演算子を使用したため、型エラーとハッシュ値の使用が生じました。
メリット:
デメリット:
配列全体の明示的なゼロ初期化 {0} を使用し、関数はポインタとサイズを受け取った、フィールドへのアクセスは厳密かつタイプに従って行いました (arr[i].x)。
メリット:
デメリット: