3
..
char arKey[1]; } Bucket;

The above is said to be flexible array,how?

arr
  • 301
  • 1
  • 3
  • 5
  • The above is incorrectly said to be a 'flexible array member'; it is not a 'flexible array member' because it has an explicit size, which removes the flexibility. It might be the basis of the code for the 'struct hack', which has somewhat pejorative overtones - quite correctly. It was sometimes necessary (or, at least, convenient) to use the struct hack before C99 standardized flexible array members. It usually (always?) worked; it wasn't guaranteed to work by the standard. – Jonathan Leffler Nov 16 '10 at 08:35
  • In C99, the `[1]` version is guaranteed to work as long as the type of the array elements is `char`, as a consequence of the rule that (the representation of) objects of any type can be accessed through `char` pointers. I'm not sure if this applies in C89/C90. – R.. GitHub STOP HELPING ICE Nov 16 '10 at 15:26

2 Answers2

2

Often the last member of a struct is given a size of 0 or 1 (despite 0 being against the standard pre-C99, it's allowed in some compilers as it has great value as a marker). As one would not normally create an array of size 0 or 1, this indicates to fellow coders that the field is used as the start of a variably sized array, extending from the final member into any available memory.

You may also find a member of the struct defining the exact length of the flexible array, just as you often find a member that contains the total size in bytes of the struct.

Links

Example

typedef struct {
    size_t len;
    char arr[];
} MyString;

size_t mystring_len(MyString const *ms) { return ms->len; }

MyString *mystring_new(char const *init)
{
    size_t len = strlen(init);
    MyString *rv = malloc(sizeof(MyString) + len + 1);
    rv->len = len;
    strncpy(rv->arr, init, len);
    return rv;
}
Community
  • 1
  • 1
Matt Joiner
  • 112,946
  • 110
  • 377
  • 526
0

Flexible arrays are supposed to have a length of 0 in C99. Using a size of 1 is C90 and is now deprecated.

Basically, such flexible arrays are created by invoking malloc with sizeof(Bucket) + array_length, where array_length is the desired size of your array. Then, dereferencing the arKey pointer (which must be the last member of your structure) will result in that extra memory being accessed, effectively implementing variable-sized objects.

See this page for more information:

http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

Gnurou
  • 7,923
  • 3
  • 22
  • 32
  • 3
    No, they do *not* have a length of `0` in C99. The standard C flexible array member is an incomplete type, with no size specified at all (eg. `char arKey[];`) – caf Nov 16 '10 at 08:49
  • @caf: I wonder why zero-size structs were forbidden? Some older compilers allowed them, and I would guess most compilers would have "done the right thing" with them but for code which explicitly triggers an error on zero-sized arrays. Note that a zero-sized array in the middle of a struct could have been useful both as a means of forcing word alignment for the following element, and also as a means of aliasing a `char[]` to the following element without having to use a `union`. – supercat Dec 05 '12 at 16:33
  • @supercat: Zero-sized objects might be disallowed because of the ambiguity that arises when you subtract pointers to two such objects, and because distinct objects are guaranteed to have distinct addresses given by `&`. – caf Dec 05 '12 at 22:51
  • @caf: I meant zero-sized arrays, btw. What you describe may well be the rationale, though one could resolve those issues by specifying that the subtraction of pointers to zero-sized objects would be Undefined Behavior, and that a zero-sized struct member may have the same address as the following member. Requiring code to declare a single-element array to implement the struct hack is far nastier than the other workarounds described. – supercat Dec 05 '12 at 23:03
  • @supercat: Well, in C99 you don't declare a single-element array - you declare a flexible array member (which has incomplete type, and thus pointer arithmetic on it is disallowed so it works substantially like your zero-sized array proposal). As far as I know, when C89 was standardised the "struct hack" wasn't widely known, so it was not a consideration. – caf Dec 05 '12 at 23:34
  • @caf: My "proposal" is the way things used to work on some compilers before they were forbidden by the standard. I guess my puzzlement is why the standard had to require that compilers reject programs containing zero-sized arrays as mal-formed rather than letting them be an Undefined Behavior or an Implementation-Defined optional feature (specifying that compilers wouldn't have to allow them, but that compilers that did allow them would have to have certain semantics). – supercat Dec 05 '12 at 23:50