Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

zero length arrays [duplicate]

Tags:

c

structure

Recently I came across a structure definition,

struct arr {
    int cnt;
    struct {
        int  size;
        int *name;
    } list[0];
};

and now I don't know the reason for list[0] being declared. What I am interested in is why is this used. Does it have any advantage? If yes, what is it?

like image 667
hue Avatar asked Jan 14 '11 11:01

hue


2 Answers

The use is for dynamic-length arrays. You can allocate the memory using malloc(), and have the array reside at the end of the structure:

struct arr *my_arr = malloc(sizeof *my_arr + 17 * sizeof *my_arr->list);
my_arr->cnt = 17;
my_arr->list[0].size = 0;
my_arr->list[1].name = "foo";

Actually being able to use 0 for the length is (as pointed out in a comment) a GCC extension. In C99, you can leave out the size literal altogether for the same effect.

Before these things were implemented, you often saw this done with a length of 1, but that complicates the allocation a bit since you must compensate when computing the memory needed.

like image 64
unwind Avatar answered Nov 16 '22 03:11

unwind


It is called "struct hack". You can search for it on SO or on the Net

http://www.google.com/search?q=struct+hack&sitesearch=stackoverflow.com/questions

Note that formally it is always illegal to declare arrays of size 0 in C. The code you provided formally is not even compilable. Most C compilers will accept 0-sized array declaration as an extension though, specifically because it is often used in "lazy" version of "struct hack" (it can rely on sizeof to determine how much memory to allocate, since 0-sized array supposedly does not affect the total size of the struct).

An arguably better implementation of struct hack uses an array of size 1

struct arr {
    int cnt;
    struct {
        int  size;
        int *name;
    } list[1];
};

It is "better" because it is formally compilable at least. In order to allocate memory for a struct with N elements in the list, standard offsetof macro is used

arr *a = malloc(offsetof(arr, list) + N * sizeof a->list);

In C99 version of the language specification the "struct hack" is supported through size-less array declaration (with empty []), since 0-sized array declarations are illegal in C99 as well.

like image 31
AnT Avatar answered Nov 16 '22 02:11

AnT