Цикличное выполнение массив фиксированного размера, не определяя его размер в C

Некоторый пример кода для запуска вопроса:

 #define FOO_COUNT 5

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

Путем это обычно выполнялось бы с помощью итераций, что касается одного примера, следующее:

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

Там должен так или иначе сделать, вышеупомянутое, явно не имея человека считает номер 5? В будущем я мог бы добавить/удалить элементы и забыть обновлять размер массива, таким образом повредив мое приложение.

6
задан James McNellis 20 June 2010 в 00:53
поделиться

7 ответов

int i = sizeof(foo)/sizeof(foo[0]);
.
16
ответ дан 8 December 2019 в 02:30
поделиться

Использовать sendinel в конце, например NULL:

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

for (char *it = foo[0]; it != NULL; it++)
{
        ...
}
12
ответ дан 8 December 2019 в 02:30
поделиться

Обычный способ сделать это - закончить массив с NULL и выполнить итерацию до тех пор, пока вы не ударите по нему.

.
2
ответ дан 8 December 2019 в 02:30
поделиться

Да.

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

Примечание: Это относится только к статически выделенным массивам. Это не будет работать для malloced или newed массивов.

.
2
ответ дан 8 December 2019 в 02:30
поделиться
size_t i = sizeof foo / sizeof *foo; // or sizeof foo / sizeof foo[0]

Это делит общее количество байт в массиве Foo (sizeof foo) на количество байт в одном элементе (sizeof *foo), давая количество элементов в массиве.

2
ответ дан 8 December 2019 в 02:30
поделиться

Yes.

sizeof(foo)/sizeof(char*)

is 5.

0
ответ дан 8 December 2019 в 02:30
поделиться

В C99 есть и другой метод, особенно если вам нужны именованные индексы, позволяющие, например, локализацию и тому подобное.

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",
};

При использовании именованного инициализатора программа остается корректной, даже если значение перечисления изменится.

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

или в любом месте программы с именованным индексом

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

Этот прием можно использовать для имитации пучков ресурсов. Объявите один enum и несколько строковых массивов с вариантами языка и используйте указатель в остальной части программы. Просто и быстро (особенно на 64-битных машинах, где получение адреса константы (строки) может быть относительно дорогостоящим. Edit: техника sizeof foo/sizeof *foo все еще работает с этим.

2
ответ дан 8 December 2019 в 02:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: