Как объявить и инициализировать этот массив структур в C, когда длина не известна до времени выполнения? - PullRequest
3 голосов
/ 02 декабря 2010

foo.c

#include "main.h"
unsigned char currentBar;
struct foo myFoo[getNumBars()];

void initMyFoo(void)
{
 currentBar=(getNumBars()-1);
 for(i=0; i<(sizeof(myFoo)/sizeof(myFoo[0])); i++)
 {
  myFoo[i].we = 1;
  myFoo[i].want = 0;
  myFoo[i].your = 0;
  myFoo[i].soul = 0;
 }
}

main.c

#include "foo.h"
unsigned char getNumBars()
{
 return getDipSwitchValues();
}
initMyFoo();

(структура foo объявлена ​​в foo.h.)

Этот код должен выполняться без жесткого кодирования числа для баров, так как количество баров будет меняться в зависимости от того, что пользователь устанавливает свои DIP-переключатели. Сейчас я не могу инициализировать myFoo; Я получаю сообщение об ошибке «Ожидается постоянное выражение в инициализаторе». Должен ли я инициализировать его как:

struct foo myFoo[];

и поменять его позже? Если так, как мне сделать myFoo [] правильной длины? У меня очевидно нет постоянной доступной, которая соответствует желаемому размеру. Нужно ли динамически выделять это или что-то?

Я нашел этот похожий ответ, но он был не слишком полезен для меня - C ++ класс с массивом структур, не зная, какой массив мне нужен

Ответы [ 3 ]

3 голосов
/ 02 декабря 2010
struct foo* myFoo;
unsigned int myFooSize;

void initMyFoo(void)
{
  myFooSize = getNumBars();
  myFoo = malloc(myFooSize * sizeof(*myFoo));
  for (i=0; i<myFooSize; i++) {
    /* ... */
  }
}

void cleanupMyFoo(void)
{
  free(myFoo);
  myFoo = NULL;
  myFooSize = 0;
}
1 голос
/ 02 декабря 2010

1 - в C99 вы можете использовать массивы переменной длины , которые позволяют создавать массивы, длина которых определяется во время выполнения.Вы также можете использовать их через расширения компилятора (GCC поддерживает их для не-C99 C и C ++), но это не переносимое решение.

int someUnknownSize = 0;

/* some code that changes someUnknownSize */

struct foo myFoo[someUnknownSize];

2 - Объявите указатель, который будет выделяться памяти во время выполнения сmalloc или calloc.

struct foo *fooPtr = 0; /* null pointer to struct foo */
int sizeToAlloc = 0;
/* determine how much to allocate/modify sizeToAlloc */
fooPtr = malloc(sizeToAlloc * sizeof(*fooPtr));

/* do stuff with the pointer - you can treat it like you would an array using [] notation */
free(fooPtr);
0 голосов
/ 02 декабря 2010

Обычно я выбираю ожидаемый максимальный размер массива и, если это необходимо, просто изменяю его размер:

type * a = calloc(sizeof(type),exp_array_size);

и после добавления нового значения в массив (да, хорошо, я воспринимаю его как стек ...), я проверяю его текущий размер по сравнению с новым:

if (current_size > max_size) {
    max_size *= 2;
    realloc(a,max_size*sizeof(type));
}
...