Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sizeof() a struct with a zero length array member

I'm confused about sizeof() output in C. Say I have:

struct foo {
    char a;
    char b;
    char c;
    char d[0];
};

I would expect sizeof(struct foo) to be 4. However, it returns 3 after compiling with gcc. Also, when compiling the code with strict settings -pedantic-errors, I get compiler errors.

Can someone help me understand this behavior?

like image 882
marcantonio Avatar asked Jan 25 '23 20:01

marcantonio


1 Answers

An array size of 0 is not legal. Section 6.7.6.2p1 of the C standard regarding Array Declarators states:

In addition to optional type qualifiers and the keyword static , the [ and ] may delimit an expression or * . If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero. The element type shall not be an incomplete or function type. The optional type qualifiers and the keyword static shall appear only in a declaration of a function parameter with an array type, and then only in the outermost array type derivation.

So because this violates a constraint, this definition invokes undefined behavior.

That being said, some compilers allow a zero length array as the last member of a struct as an extension. GCC does this. In this case, it works the same as a flexible array member.

The standard compliant way to do this is to leave the size blank:

struct foo {
    char a;
    char b;
    char c;
    char d[];
};

In both cases, the flexible array member is not included in the size of the structure, which is why you get 3 for the size instead of 4 (although the presence of padding in a struct is up to the implementation). This also means that such a struct cannot be a member of an array (at least not without some fishy manual pointer manipulation).

The way you would use such a struct would be to dynamically allocate space for it plus a number of elements of the last member. For example:

struct foo *my_foo = malloc(sizeof(*my_foo) + (sizeof(char) * number_of_elements));
like image 131
dbush Avatar answered Feb 01 '23 22:02

dbush