2016-07-22 2 views
1

Кто-нибудь знает, есть ли способ инициализировать структуру, содержащую массив переменной длины, без инициализации массива сначала в отдельной переменной (и без использования malloc)?Инициализация структуры с массивом переменной длины в C

Моя структура выглядит следующим образом:

struct my_struct { 
    int *values; 
    int size; 
} 

Сейчас в моем коде у меня есть что:

void my_function (int size) { 
    int values[size]; 
    struct my_struct mystr = { 
     .values = values, 
     .size = size 
    }; 
    ... 
} 

(массив инициализируется первым, то структура Это работает, но это выглядит неудобно. объявить отдельную переменную для массива.)

Возможно, это будет работать:

void my_function (int size) { 
    struct my_struct mystr = { 
     .values = calloc (size, sizeof (int)), 
     .size = size 
    }; 
    ... 
} 

(но я не хочу использовать mallocs)

Но то, что я хотел бы написать что-то вроде:

void my_function (int size) { 
    struct my_struct mystr = { 
     .values = (int[size]){}, 
     .size = size 
    }; 
    ... 
} 

Любая идея?

+1

Вы хотите иметь массив без выделения пространства для него? – GMichael

+0

Я знаю, что мне нужно выделить пространство для массива, но я хотел бы сделать это без использования промежуточной переменной, такой как 'int values ​​[size];'. – FClad

+0

Что не так с '.values ​​= calloc (size, sizeof (int)),'? – GMichael

ответ

3

Прежде всего обратите внимание, что вы не можете использовать массив из своего стека, если хотите вернуть свою структуру.

int values[size]; 
struct my_struct mystr = { 
    .values = values, 
    .size = size 
}; 
return mystr; 

Это не будет работать, так как срок службы values заканчивается, когда вы вернетесь. То же самое относится, если вы попытаетесь сохранить mystr в значении, указанном параметром вашей функции.

Очевидно, что вы этого не делаете, но я думаю, что стоит упомянуть в любом случае.


Ответ на ваш вопрос: это зависит от ситуации.

Вы уверены, что size небольшой? Или ваш стек будет переполняться в int values[size]. Является ли оно маленьким и предсказуемым? Придерживайтесь первого решения. Если он может быть большим или зависит от пользователя, обязательно используйте malloc.

Вы каким-то образом возвращаете или сохраняете постоянный указатель на свою структуру или ценности? Используйте malloc (см. Мое первое замечание).

В качестве альтернативы вы также можете использовать struct hack, но тогда вам нужно будет malloc всего mystr в любом случае. более


Одна вещь, Вы писали:

(.. Массив инициализируется первый, то структура Это работает, но выглядит неуклюжим объявить отдельную переменную для массива)

Я не уверен, что вы имеете в виду, но int * - это только sizeof(intptr_t), независимо от размера массива. Таким образом, вы не выделяете дважды память для 1 массива, если это то, о чем вы думаете.

+1

'sizeof (int *)' не обязательно равен 'sizeof (intptr_t)'. Я думаю, вы пропустили это; OP не заботится о производительности или использовании памяти в этом вопросе. Он хочет быть более выразительным ... Эти две концепции работают ортогонально. – Sebivor

-1

Инициализатор - это именованные объекты, инициализированные списком инициализаторов. За пределами тела функции объект имеет статическую продолжительность хранения. Таким образом, можно использовать адрес такого объекта. С небольшой помощью от вариационных макросов вы можете попробовать →

#include <stdio.h> 

struct test { 
    int count; 
    int *values; 
} test[] = { 
#define init(...) { .count=sizeof((int[]) {__VA_ARGS__})/sizeof(int), .values=(int *)&(int []){__VA_ARGS__} } 
       init(0,1,2,3,4), 
       init(2,4,6,8), 
       init(1,3), 
       init(42) 
      }; 
#define test_size ((int) (sizeof test/sizeof *test)) 

int main(void) 
{ 
    for(int array=0; array<test_size; ++array) { 
    printf("array %d (%d) : [ ", array+1, test[array].count); 
    for(int i=0; i<test[array].count; ++i) 
     printf("%d ", test[array].values[i]); 
    puts("]"); 
    } 
    return 0; 
} 
Смежные вопросы