50

I have an array of structs that I created somewhere in my program.

Later, I want to iterate through that, but I don't have the size of the array.

How can I iterate through the elements? Or do I need to store the size somewhere?

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
Andrew Johnson
  • 13,108
  • 13
  • 75
  • 116

4 Answers4

64

If the size of the array is known at compile time, you can use the structure size to determine the number of elements.

struct foo fooarr[10];

for(i = 0; i < sizeof(fooarr) / sizeof(struct foo); i++)
{
  do_something(fooarr[i].data);
}

If it is not known at compile time, you will need to store a size somewhere or create a special terminator value at the end of the array.

Variable Length Coder
  • 7,958
  • 2
  • 25
  • 29
29

You can store the size somewhere, or you can have a struct with a special value set that you use as a sentinel, the same way that \0 indicates the end of a string.

pevik
  • 4,523
  • 3
  • 33
  • 44
David Seiler
  • 9,557
  • 2
  • 31
  • 39
  • 4
    +1 I usually use pointers to structs so that I can be sure `NULL` is a unique sentinel. – Chris Lutz Oct 20 '09 at 23:19
  • 8
    I think following the null-terminated-string model is a bad idea – hasen Oct 20 '09 at 23:35
  • 1
    @hasen j: I agree, unless you know you always have to iterate through the entire array every time, in which case a sentinel can clarify code slightly. The trouble with the sentinel is you can end up with O(N) behavior where O(1) would have done, and not always realize it. – quark Oct 20 '09 at 23:41
18

It depends. If it's a dynamically allocated array, that is, you created it calling malloc, then as others suggest you must either save the size of the array/number of elements somewhere or have a sentinel (a struct with a special value, that will be the last one).

If it's a static array, you can sizeof it's size/the size of one element. For example:

int array[10], array_size;
...
array_size = sizeof(array)/sizeof(int);

Note that, unless it's global, this only works in the scope where you initialized the array, because if you past it to another function it gets decayed to a pointer.

Hope it helps.

AntonioMO
  • 898
  • 1
  • 6
  • 16
  • 6
    It is not about whether the array is dynamically allocated or not. It is about wheteher you allowed array type to decay to pointer type. For example, I can create a dynamicillay allocated array like this `int (*a)[10] = malloc(sizeof *a)` and use `sizeof *a / sizeof **a` to "determine" the number of elements later. No need to store the size separately. – AnT stands with Russia Oct 20 '09 at 23:35
  • 8
    +1, although it's slightly preferable to do `sizeof(array)/sizeof(array[0])` so that it still works if the underlying array type changes; this form also allows you to easily define a macro, e.g. `#define ARRAY_COUNT(a) (sizeof(a)/(sizeof(a[0]))`. – Adam Rosenfield Oct 20 '09 at 23:35
  • The same is true about passing it to a function. It all depends on how you pass it. – AnT stands with Russia Oct 20 '09 at 23:35
  • @AdamRosenfield: That should be an answer. (And then I can edit it to add the missing parenthesis...) – endolith Mar 13 '13 at 21:36
1

I think you should store the size somewhere.

The null-terminated-string kind of model for determining array length is a bad idea. For instance, getting the size of the array will be O(N) when it could very easily have been O(1) otherwise.

Having that said, a good solution might be glib's Arrays, they have the added advantage of expanding automatically if you need to add more items.

P.S. to be completely honest, I haven't used much of glib, but I think it's a (very) reputable library.

hasen
  • 161,647
  • 65
  • 194
  • 231