tags:

views:

262

answers:

8

Some example code to start the question:

 #define FOO_COUNT 5

 static const char *foo[] = {
       "123",
       "456",
       "789",
       "987",
       "654"
 };

The way this would normally be iterated over, as for one example, is the following:

int i = FOO_COUNT;
while (--i >= 0) {
 printf("%s\n", foo[i]);

Is there anyway to do the above without explicitly having the human count the number 5? In the future I might add/remove elements and forget to update the size of the array, thus breaking my app.

+14  A: 
int i = sizeof(foo)/sizeof(foo[0]);
aJ
would this still work if the character pointers in foo pointed to character strings of variable size?
randombits
yes (15 char limit)
aJ
so if any element exceeds 15 characters, this check will fail? probably better to use the NULL sentinel then? thanks again.
randombits
It will not fail. sizeof[foo[0]) ==> sizeof(char*); Number of character does not matter.
aJ
ok, wasn't sure what you're referring to by 15 char limit in your comment above
randombits
The 15 char limit part of the comment means that he was just adding extra characters to meet the 15 character minimum for comments in Stack Overflow. His answer as just "yes", but Stack Overflow doesn't like comments that short.
Brian Campbell
Note that `i` above is a compile-time constant, so you can do: `#define N sizeof foo / sizeof foo[0]` followed by `int data[N];`. That is valid even for C89. Also, the parentheses are not required if `sizeof` operator is used with a value instead of a type.
Alok
The first sentence above should read, "...the RHS in the definition of `i` is a compile-time constant".
Alok
Sorry for the confusion. Thanks @Brian Campbell for clarifying what I meant.
aJ
A: 

Yes.

sizeof(foo)/sizeof(char*)

is 5.

Pavel Radzivilovsky
+2  A: 

The usual way to do this is to end the array with NULL and iterate until you hit that.

diciu
+2  A: 

Yes.

int i = sizeof(foo) / sizeof(char*);

Note: This only applies to statically allocated arrays. It will not work for malloced or newed arrays.

ruibm
+11  A: 

Use a sentinel at the end, such as NULL:

static const char *foo[] = {
       "123",
       "456",
       "789",
       "987",
       "654",
       NULL
};

for (char *it = foo[0]; it != NULL; it++)
{
        ...
}
Ignacio Vazquez-Abrams
+2  A: 
size_t i = sizeof foo / sizeof *foo; // or sizeof foo / sizeof foo[0]

This divides the total number of bytes in the foo array (sizeof foo) by the number of bytes in a single element (sizeof *foo), giving the number of elements in the array.

John Bode
+2  A: 

There's also another method in C99, especially if you want named indexes, allowing for instance localization and such.

enum STRINGS {
  STR_THING1,
  STR_THING2,
  STR_THING3,
  STR_THING4,
  STR_WHATEVER,

  STR_MAX         /* Always put this one at the end, as the counting starts at 0 */
                  /* this one will be defined as the number of elements */
}     

static const char *foo[STR_MAX] = {
  [STR_THING1]   = "123", 
  [STR_THING2]   = "456",
  [STR_THING3]   = "789",
  [STR_THING4]   = "987",
  [STR_WHATEVER] = "OR Something else",
};

By using named initializer the program still is correct even if an enum value changes.

for (i = STR_THING1; i<STR_MAX; i++)
  puts(foo[i]);

or anywhere in the program with the named index

  printf("thing2 is %s\n", foo[STR_THING3]);

This technique can be used to simulate ressource bundles. Declare one enum and several string arrays with language variants and use a pointer in the rest of the program. Simple and fast (especially on 64bit machines where getting the address of a constant (string) can be relatively costly. Edit: the sizeof foo/sizeof *foo technique still works with this.

tristopia
A: 

For some application, try and Catch would work.

iampat
Even if C had `try` and `catch`, I don't see how they're relevant to iterating over an array.
Nefrubyr