I have found a peculiar behaviour in C. Consider the below code:
struct s { int a; }; struct z { int a; struct s b[]; }; int main(void) { return 0; }
It compiles just fine. Then change the order of the members of struct z
like so
struct z { struct s b[]; int a; };
And all of a sudden we get the compilation error field has incomplete type 'struct s []'
.
Why is that?
Struct members are stored in the order they are declared. (This is required by the C99 standard, as mentioned here earlier.) If necessary, padding is added before each struct member, to ensure correct alignment. Each primitive type T requires an alignment of sizeof(T) bytes.
They will not necessarily be contiguous in memory. This is due to struct padding. then they most likely will not be. However, in your particular case, you will still likely get padding after gender , to realign the struct to 8 bytes.
A structure T cannot contain itself.
Can C++ struct have member functions? Yes, they can.
The order of fields in a struct
does matter - the compiler is not allowed to reorder fields, so the size of the struct
may change as the result of adding some padding.
In this case, however, you are defining a so-called flexible member, an array the size of which you can change. The rules for flexible members are that
struct
, andstruct
must have at least one member in addition to the flexible one.Take a look at this Q&A for a small illustration on using flexible structure members.
The compiler can't calculate how much memory struct s b[];
will consume. This means that if the structure has any fields after it, the compiler can't figure out the where those fields are.
It used to be (in old versions of C) that (e.g.) struct s b[];
wasn't allowed as a member of a structure. This made efficient memory management annoying. For a simple example, imagine you've got a structure containing a "name" string (that could be just a few characters or a lot of them). You could use a fixed size array that's big enough for the largest name (which wastes space), or use a pointer and allocate 2 pieces of memory (one for the structure and one for the variable length name string). Alternatively, you could use a pointer and make it point to extra space past the end of the structure, which ends up something like this:
length = strlen(my_string); foo = malloc(sizeof(MYSTRUCTURE) + length + 1); foo->name = (void *)foo + sizeof(MYSTRUCTURE); // Set pointer to extra bytes past end of structure memcpy(foo->name, my_string, length + 1);
This was the most efficient option; but it's also ugly and error prone.
To work around that, compilers added non-standard extensions to allow "unknown size arrays" at the end of the structure. This made it a little easier for programmers and made it a little more efficient (as there's no need for the additional pointer member). This ended up being adopted by the C standard (maybe in C99 - I don't remember).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With