开发者

Looping a fixed size array without defining its size in C

Some example code to start the question:

 #define FOO_COUNT 5

 stat开发者_JS百科ic 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.


int i = sizeof(foo)/sizeof(foo[0]);


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++)
{
        ...
}


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


Yes.

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

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


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.


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.


Yes.

sizeof(foo)/sizeof(char*)

is 5.


For some application, try and Catch would work.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜