Tuntable
Tuntable

Reputation: 3574

C flexible arrays vs pointers

struct ss {
    char foo[];
    char bar[3];
    int bazSize;
    char baz[];
}

In the above, foo is clearly a pointer 4 or 8 bytes long. bar is an array, 3 bytes long. baz used to be a pointer, 8 bytes long. But in C99 baz is a flexible array. (Traditionally defined as baz[0].)

What are the rules? How does the compiler know that foo is a completely different type of thing than baz? How cannot this just break any code that happens to have a pointer at the end of a struct? Is [] now different from *?

Upvotes: 2

Views: 1143

Answers (3)

Tuntable
Tuntable

Reputation: 3574

The problem is that char *foo and char foo[] are only the same thing in some contexts (like function parameter declaration) and not others (like structure field declarations).

(I have not hacked C for a long while.)

Upvotes: 1

chqrlie
chqrlie

Reputation: 144780

Your structure declaration is incorrect: char foo[]; can only appear as the last member, and it is missing a ; at the end. Here is correct declaration:

struct ss {
    char *foo;
    char bar[3];
    int bazSize;
    char baz[];
};

We have a pointer foo and a flexible array baz at the end. When allocating such a structure from the heap, the actual space for the last member must be known and cannot be changed without reallocating the whose structure which may be complicated if the structure it referred to from various other places. Flexible arrays save space but are not flexible at all.

Advantages of the flexible array:

  • save space
  • save one indirection
  • allocate in one step
  • baz is never NULL

Conversely, making baz a pointer requires separate allocation of the array it points to. This disadvantage in size, code and speed comes with compensations.

Advantages of the pointer version:

  • baz can be NULL to specify no data.
  • baz can be allocated on demand, when the actual size is known.
  • baz can be reallocated easily.

So which you should use depends on how you use these structures. The syntax at point of use is the same, but the compiler has seen the actual declaration and will generate the appropriate code.

Upvotes: 4

Daniel Danilov
Daniel Danilov

Reputation: 1

Firstly, you need to initialise foo and baz for the code to actually compile. Then it is clear to the compiler what the difference between the two are.

Upvotes: 0

Related Questions