26

I have encountered this piece of code:

struct test                   
{                                        
 uint32       num_fields;            
 char array_field [];               
}; 

How can I understand array_field? Is this a gcc extension for the C language?

Busti
  • 5,492
  • 2
  • 21
  • 34
FaceBro
  • 787
  • 2
  • 13
  • 29

2 Answers2

22

It's a C99 feature, called flexible array member which is typically used to create a variable length array.

It can only be specified as the last member of a struct without specifying the size (as in array_field [];).


For example, you can do the following and the member arr will have 5 bytes allocated for it:

struct flexi_example
{
int data;
char arr[];
};


struct flexi_example *obj;

obj = malloc(sizeof (struct flexi_example) + 5);

Its pros/cons discussed here:

Flexible array members in C - bad?

Community
  • 1
  • 1
P.P
  • 117,907
  • 20
  • 175
  • 238
  • Any idea why this was added to C instead of just using pointers? I hardly see why to use arrays at all except to allocate some pre-determined space on the stack. This doesn't give you that benefit. – xaxxon Jun 19 '13 at 08:03
  • I finally got the point when I printf the sizeof of the struct. Actually, the array_field does not occupy any bytes, it's the same thing as array_field[0], which is used to create a variable length array in gcc. – FaceBro Jun 19 '13 at 08:06
  • @undur_gongor sorry for the delay. I was commuting ;). – P.P Jun 19 '13 at 08:47
  • @xaxxon It's not an irreplaceable feature. I believe it was added based on the GNU extension zero length member. Details here: http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html – P.P Jun 19 '13 at 08:48
  • 2
    @xaxxon It's added because with this feature, you can have true VLAs *inside* a struct, and you don't have to mallocate memory *twice.* This increases readability and decreases memory fragmentation and the number of pointer traversals (and thus perhaps boosts performance a little bit). –  Jun 19 '13 at 08:50
  • 3
    @H2CO3: Flexible array members are not VLAs. In particular, `sizeof` applied to the struct doesn't include the size of the array member; you just have to keep track of that yourself. – Keith Thompson Jun 24 '13 at 16:35
  • @KeithThompson Yes I know that, still the reasoning is correct I believe. –  Jun 24 '13 at 21:08
  • @H2CO3: VLAs and flexible array members have similarities, but they're distinct features. I suggest that referring to flexible array members as VLAs is likely to cause confusion. – Keith Thompson Jun 24 '13 at 21:19
  • @KeithThompson Yes, you're correct with regards to wording, sorry about that. Under "reasoning" I meant the response I gave to xaxxon. –  Jun 24 '13 at 21:21
  • 1
    The flexible array member was added to formalize the [long existing and relied upon "struct hack"](http://stackoverflow.com/search?tab=votes&q=%2b[c]%20%22struct%20hack%22) (that search really isn't complete, as some instances are left off, but without the quotes a lot of junk creeps in). – dmckee --- ex-moderator kitten Nov 08 '13 at 02:53
3

Such structures are usually allocated on the heap with a calculated size, with code such as the following:

#include <stddef.h>

struct test * test_new(uint32 num_fields)
{
    size_t sizeBeforeArray = offsetof(struct test, array_field);
    size_t sizeOfArray = num_fields * sizeof(char);
    struct test * ret = malloc(sizeBeforeArray + sizeOfArray);
    if(NULL != ret)
    {
        ret->num_fields = num_fields;
    }
    return ret;
}
undur_gongor
  • 15,657
  • 5
  • 63
  • 75
Medinoc
  • 6,577
  • 20
  • 42