Search code examples
carraysstructiterationboundary

How to iterate over of an array of structures


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
}

Solution

  • 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.