16

私のアプリケーションでは、構造体の配列を使用しており、配列を反復処理する必要があります。それを行う適切な方法は何ですか?配列の最後に到達したかどうかを確認するにはどうすればよいですか?

// structure
struct MyData {
  int count;
  char name[20];
  float average;
}

このように繰り返してみましたが、アプリケーションがクラッシュします:

struct MyData data[2] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;

while (*ptr != NULL) {
  // print the contents, works ok for 2 elements

  ptr++; // increment the pointer
}
4

2 に答える 2

28

構造体の配列はどのように割り当てられますか

あなたの場合、MyData[2]配列はメモリ内で次のようになります。

| count | name | average | count | name | average |
^ -- your ptr points here 

これは、 size の単一の連続空間2 * sizeof (struct MyData)です。

操作を実行するたびにptr++、ポインターは配列内の次の構造体に移動します。つまり、単一の のサイズが考慮されますstruct MyData

| count | name | average | count | name | average |
                         ^ -- after ptr++ your ptr points here

次々と、ポインタは配列の直後ptr++のメモリを指します。

| count | name | average | count | name | average | 
                                                  ^ -- another ptr++ and your ptr points here

ポインターを逆参照するptrと、まだ使用されていない、または割り当てられていないメモリにアクセスします。これは未定義の動作であり、そのためアプリケーションがクラッシュします。

反復する方法は?

それにはいくつかの方法があります。すべての場合にすべての方法が適用できるわけではないことに注意してください。

シンプルな

多くの場合、単に配列のサイズを知っているだけです。その後、通常のforループを使用してコンテンツを反復処理できます。

int len = 2;
struct MyData data[len] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;
for (int i=0; i<len; i++, ptr++ ) {
   // do your thing with the ptr
   // and note that ptr gets increased inside for
}

sizeof を使用して配列の長さを決定する

struct MyData data[2] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;
struct MyData* endPtr = data + sizeof(data)/sizeof(data[0]);
while ( ptr < endPtr ){
   // do your thing with the ptr
   ptr++;
}

は要素のsizeof(data)/sizeof(data[0])量を計算します。配列の合計サイズを取得し、それを 1 つの要素のサイズで割ります。

この方法には欠点があります。配列がポインタとして宣言されている場合は使用できません! たとえば、配列をパラメーターとして関数に渡すと、通常はポインターに変換され、配列のサイズを決定できません。

于 2013-09-20T10:52:18.590 に答える