0

I can't guess the use of constructs such as

struct 
{
    uint64_t offsets[0];
} table; 

Please give me some hint with regard to this.

Shraddha
  • 2,427
  • 5
  • 17
  • 21
  • How is this different from : `struct { uint64_t offsets; } table;` – Shraddha Dec 25 '12 at 06:46
  • 1
    What you have now have no practical uses, aside from something very implementation-specific. It resembles the classic "struct hack", but the declaration you provided cannot be used for that purpose. – AnT stands with Russia Dec 25 '12 at 06:48
  • It is different in that `uint64_t offsets` would introduce a field of type `uint64_t`. Meanwhile, an array of size `0` (if it compiles in your compiler) introduces no data at all. Your variable `table` is empty. It itself has size `0`, which is why I say that it has no practical uses. Actually, the only use it has is to occupy some unique address in memory. – AnT stands with Russia Dec 25 '12 at 07:02

3 Answers3

5

The code you posted is formally invalid. Formally C language does not support arrays of size 0.

Some compilers (with loose/legacy error checking) allow an array of size zero at the end of the struct, which was sometimes used to implement so called "struct hack". (A better approach would be to use a trailing array of size 1.) However your declaration does not provide for that use. "Struct hack" requires a named struct type, and the actual objects have to be dynamically allocated. In your case the struct type is left unnamed, and the variable table is defined non-dynamically. So, "struct hack" is out of question here, assuming you reproduced the code correctly.

So, even it it compiles, you end up with variable table that contains no usable data. The only use for this variable (if declared with static storage duration) is to produce an unique address constant through &table expression (a pointer of "pointer to an anonymous struct" type).

One way to turn your declaration into something closer to the "struct hack" is to add a typedef in front of it

typedef struct 
{
  uint64_t offsets[0];
} table; 

However, a "human-generated" struct declaration for a "struct hack" will typically include other data fields before the flexible array declaration (without them there's simply no point in choosing "struct hack" over an ordinary array).

Community
  • 1
  • 1
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
1

This is a trick that lets you cast a memory block of any size to your pointer type, and make the last array member a variable-length array. Although probably not standard, this works because C arrays are not bounds-checked.

Here's a very simple example demonstrating it:

typedef struct Foo
{
    int count;
    int array[0];
} Foo;

Foo* foo = (Foo*)malloc(sizeof(Foo) + 5 * sizeof(int));
foo->count = 5;

You can then use the count field to know the number of valid elements inside the Foo*. Since, as mentioned above, C arrays are not bounds-checked, neither the compiler nor the runtime will catch that foo->array has a size of 0 when you try to read or write to it.

zneak
  • 134,922
  • 42
  • 253
  • 328
  • The OP's code used an unnamed struct and defines variable `table` of that type. How are you proposing using an unnamed struct for the purposes you described in your answer? And what is the purpose of variable `table`? (Additionally, this is C, meaning that in your answer you declared `struct Foo` not just `Foo`). – AnT stands with Russia Dec 25 '12 at 06:54
  • 1
    @AndreyT, no need to be so aggressive. I was assuming the "such as" part of OP's question meant that this is not actual code he found, but rather the pattern he finds. (Also, I just typedeffed my struct to make it work.) – zneak Dec 25 '12 at 07:00
  • So basically it means that `0` just fools the compiler by adhering to the fact that programmer needs to put something inside the `[]` when an array is defined inside the structure ? – Shraddha Dec 25 '12 at 07:10
  • 1
    @zneak: I'm not trying to be aggressive. I'm trying to be brief and to the point. "The margins of this comment are too small to contain too many pleasantries". – AnT stands with Russia Dec 25 '12 at 07:11
  • 1
    @user1826830, that's it. (But be careful with that. Accessing an element outside the bounds of an array is undefined behavior. It may work with your platform and your compiler, but it's definitely not clean.) – zneak Dec 25 '12 at 07:11
0

You have defined unnamed struct actually table is object not a struct name.

So,If you have this declaration

typedef struct 
{
    uint64_t offsets[0];
} table; 

Or,

   struct table
    {
        uint64_t offsets[0];
    } table; 

Then ,this is called variable length array (called struct hack).

There is restriction that,It should be the last member of the struct.

For more about it see this article on struct hack

Omkant
  • 9,018
  • 8
  • 39
  • 59
  • 2
    This is not a "struct hack". "Struct hack" would require a named struct type and dynamic memory allocation. In the above example the type is not named and the variable `table` is immediately declared. – AnT stands with Russia Dec 25 '12 at 06:49
  • @amorenoc: Formally, it is simply illegal. So, "slightly different" is an understatement. But in the compilers that allow it the semantics is the same as for flexible array member in C99, unless I'm missing something. Am I? – AnT stands with Russia Dec 25 '12 at 07:05