How to iterate over of an array of structures

Dariusz picture Dariusz · Sep 20, 2013 · Viewed 40.2k times · Source

In my application I use an array of structs and I need to iterate over the array. What is the proper way to do it? How can I check if I have reached the end of the array?

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

I have tried iterating like this, but my application crashes:

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
}

Answer

Dariusz picture Dariusz · Sep 20, 2013

How is an array of structs allocated

In your case, the MyData[2] array looks like this in memory:

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

This is a single, continuous space with size 2 * sizeof (struct MyData).

Whenever you perform a ptr++ operation the pointer will move to the next structure in the array, which means that it takes into account the size of a single struct MyData.

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

After another ptr++ your pointer will point to the memory just after your array.

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

When you dereference your ptr pointer you access memory which is not yet used or even allocated. This is undefined behavior and because of that your application crashes.

How to iterate?

There are several ways to do it. Note that not all ways are applicable in all cases.

A simple for

Very often we simply know the size of the array. We can then just use a normal for loop to iterate over the contents.

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
}

Using sizeof to determine array length

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++;
}

The sizeof(data)/sizeof(data[0]) calculates the amount of elements: gets the total size of an array and divides it by the size of a single element.

This method has its drawbacks. It can not be used when the array is declared as a pointer! For example, when we pass the array as a parameter to a function it usually gets converted to a pointer - and then we can not determine the size of the array.