Возможно ли установить размер массива внутри структуры во время выполнения?

У меня есть структура, как показано ниже:

struct Query {  
    int     pages[];
    int     currentpage;
};

Мне было интересно, можно ли установить размер этого массива после создания структуры.

Query new = malloc(sizeof(struct Query));

После этого, я буду выполнять некоторые вычисления, которые затем скажут мне размер, который должен быть pages[]. Если pages[] должен быть размером 4, как я могу установить его как таковой?

Ответы

Ответ 1

Измените тип элемента pages на указатель.

struct Query {  
    int *pages;
    int currentpage;
};

struct Query *test = malloc(sizeof(struct Query));

if (test != NULL)
{
   //your calculations

   test->pages = malloc(result_of_your_calcs);
   if (test->pages != NULL)
   {
      // YOUR STUFF
   }
   else
   {
      // ERROR
   }
}
else
{
   // ERROR
}

Когда вы free свою структуру, вы должны сделать это наоборот.

free(test->pages);
free(test);

Ответ 2

В C99 вы можете использовать Гибкие элементы массива:

struct Query {  
    int currentpage;
    int pages[]; /* Must be the last member */
};

struct Query *new = malloc(sizeof(struct Query) + sizeof(int) * 4);

Ответ 3

Вы можете использовать элемент Гибкий массив (подробнее в @AlterMann answer) (C99 +) или массив Нулевая длина ( GNU C).

Цитата из https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html,

В GNU C. допустимы массивы нулевой длины. Они очень полезны в качестве последнего элемента структуры, который действительно является заголовком для объекта переменной длины:

struct line {
   int length;
   char contents[0];
};

struct line *thisline = (struct line *)
   malloc (sizeof (struct line) + this_length);
thisline->length = this_length;

Для стандартного C90 связанный сайт упоминает

В ISO C90 вам нужно указать contents длину 1, что означает либо свободное пространство, либо сложность аргумента malloc.

Это означает, что для того, чтобы код работал в стандартном C90/C89, char contents[0]; должен быть char contents[1];.

Ответ 4

Лучшим решением было бы использовать указатели на int вместо массива.

Вам нужно будет изменить:

int pages[];

to:

int *pages;

а затем динамически распределите его следующим образом:

Query *new = malloc(sizeof(struct Query));
if (new == NULL)
    printf ("Error\n");
else
{
    new->pages = malloc(4*sizeof(int));
    if (new->pages == NULL)
       printf ("Error\n");
}

В противном случае, если вы хотите сохранить свой формат, вы будете использовать режим C99. Объявите pages в качестве последнего члена вашей структуры, например:

struct Query {  
    int currentpage;
    int pages[];
};

а затем выполните:

Query *new = malloc(sizeof(struct Query) + 4*sizeof(int));

Ответ 5

Объявите его как указатель и используйте malloc после

struct Query {  
    int * pages;
    int   currentpage;
};

. . .

struct Query obj;
obj.pages = malloc(n * sizeof(int));   // n is the length you want