2011-12-16 3 views
2
  1. Как я буду динамически выделять массив из struct Register с каждым регистром, имеющим динамически выделенный массив struct Field?
  2. Как я могу получить доступ к каждому из этих участников (могу ли я использовать Register_A.FieldArray[23].High?)?
  3. Как я могу эффективно инициализировать структуру регистров (при условии, что массив структур регистров является большим)? (Как и сегмент данных, не тратя Compute)Динамически выделять структуру и массив в нем в C

    struct Field 
    { 
        char High;     
        char Low;     
        char Attribute; 
    }; 
    
    struct Register 
    { 
        unsigned int ResetValue; 
        struct Field FieldArray[]; 
    }; 
    

ответ

3

Я решительно отговариваю вас от использования гибкого массива, потому что это не что иное, как клочья. Вы должны вместо этого объявить и использовать его как struct Field *, malloc с его размером, как и любой другой динамический массив.

Тем не менее, к malloc с размером массива n_elem:

struct Register register = malloc(sizeof(*register) + n_elem * sizeof(*register->FieldArray)); 

Чтобы получить доступ к элементам:

char high = register->FieldArray[0].High; 

Для инициализации: in gcc, at least, можно инициализировать часть массива статически, как любой другой статический массив. Я не уверен, как справляются с другими компиляторами.


Почему гибкие массивы не рекомендуется:

Я свяжусь this post, но я не думаю, что ответ является полным (большинство из уныния, потому что это с-99 только), так что я Я добавлю свои мысли.
Это исключение. По сути, вы объявляете массив равным нулю и каждый раз получая доступ к нему за пределы, только в той степени, в какой вы выделили. Вы не можете использовать структуру с гибким массивом точно так же, как любая другая структура, например. вы не можете принять гибкий массив sizeof. Если вы объявляете статический или массив из них, вы не можете использовать элемент массива, потому что для него нет места.

Пример использования их в массиве:

#include <stdio.h> 

struct test { 
     int val; 
     int arr[]; 
}; 

int main() { 
     struct test tarr[2]; 
     printf("%p\n%p\n", &tarr[0].arr[0], &tarr[1].val); 
} 

Выход:

0x7fff59b67164 
0x7fff59b67164 

Они по тому же адресу. Если вы попытаетесь написать члену массива, вы перепишете следующий объект. Если вы попытаетесь прочитать его, вы будете читать данные со следующего объекта. В зависимости от дополнения, это может быть даже бессмысленным значением из прокладки.

Это как заявления goto, оба потенциально полезны, но чаще всего плохая идея. Если вы не знаете, почему они опасны, вы не должны их использовать (в реальном коде, это неплохая идея, чтобы поиграть с ними в тестовой программе, чтобы увидеть, как правильно их использовать и как они могут внедрять проблемы).

+0

+1 для предотвращения использования гибкого массива (не говоря уже об ошибке) – pmg

+1

Почему использование гибкой решетки обескуражено? Я думал, что под капотом это так же, как с помощью указателей. Может ли он использоваться в этом случае? – Jean

+0

@alertjean: прочитайте раздел 6.7.2.1 в [Стандарт C99] (http://www.open-std.org/JTC1/sc22/wg14/www/docs/n1256.pdf) и сделайте собственные выводы. – pmg

0

Вы собираетесь должны знать, насколько большой FieldArray есть. Если он не исправлен, вам нужно объявить с максимальным значением. Тогда вы можете просто Alloc Реестр и доступ, как было указано

1

способ сделать это путем изменения размера struct Register:

struct Register 
{ 
    unsigned int ResetValue; 
    struct Field FieldArray[1]; 
}; 
struct Register *Register_Create() 
{ 
    struct Register *reg = calloc(1, sizeof(struct Register) - sizeof(struct Field)); 
    // check for NULL pointer 
    return reg; 
} 

struct Register *Register_SetSize(struct Register *reg, size_t size) 
{ 
    // check for NULL 
    reg = realloc(reg, sizeof(struct Register) + sizeof(struct Field) * (size - 1)); 
    // check for NULL 
    return reg; 
} 

Вот пример того, как использовать этот :

struct Register *reg = Register_Create(); 
reg = Register_SetSize(register, 5); 
// You now have space for 5 elements in reg->FieldArray 
reg->FieldArray[3].High = 'B'; 

Имейте в виду, что это решение работает только если FieldArray помещается в конце struct.

0

Элементы гибкого массива являются частью C99.

  1. можно выделить struc с гибким элементом массива так же, как вы думаете, вы должны: malloc(sizeof(struct Register) + sizeof(struct Field[n])), где n размера вы хотите. Не забудьте инициализировать массив и следить за n, лучше посвящая члена к этой цели
  2. да

КСТАТИ: malloc выше, может тратить несколько байт из-за дополнения, но обычно это не стоит думать о точной формуле. Минимальный размер макс и использует offsetof.

Смежные вопросы