Одноэлементный массив в структуре - PullRequest
9 голосов
/ 30 декабря 2010

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

typedef struct Bitmapset
{
 int nwords;
 uint32 words[1];
} Bitmapset;

Чтобы было удобно для последнего динамического выделения?

Ответы [ 2 ]

16 голосов
/ 30 декабря 2010

Одним словом, да.

По сути, C99 может сделать это с помощью гибкого элемента массива :

uint32 words[];

Некоторые компиляторы до C99 позволяют вам:

uint32 words[0];

Но способ гарантировать его работу на всех компиляторах:

uint32 words[1];

И затем, независимо от того, как он объявлен, вы можете выделить объект с помощью:

Bitmapset *allocate(int n)
{
    Bitmapset *p = malloc(offsetof(Bitmapset, words) + n * sizeof(p->words[0]));
    p->nwords = n;
    return p;
}

Хотя для достижения наилучших результатов вы должны использовать size_t вместо int.

6 голосов
/ 30 декабря 2010

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

-----------------
| nwords   |  3 |
| words[0] | 10 |
| words[1] | 20 |
| words[2] | 30 |
-----------------

Таким образом, вы получите переменную времени выполнения uint32, "зависающую" в конце вашегоstruct, но доступная, как если бы они были определены внутри структуры.Это в основном (ab) использование факта, что C не выполняет проверку границ массива во время выполнения, чтобы позволить вам написать код как:

for (int i = 0; i < myset.nwords; i++) {
  printf("%d\n", myset.words[i]);
}
...