0

次のような構成の使用を推測することはできません

struct 
{
    uint64_t offsets[0];
} table; 

これに関するヒントを教えてください。

4

3 に答える 3

5

投稿したコードは正式に無効です。正式には、C言語はサイズの配列をサポートしていません0

一部のコンパイラ(ルーズ/レガシーエラーチェック付き)では、構造体の最後にサイズ0の配列を許可します。これは、いわゆる「構造体ハック」を実装するために使用されることがありました。(より良いアプローチは、サイズ1の末尾の配列を使用することです。)ただし、宣言ではその使用は規定されていません。「構造体ハック」には名前付きの構造体タイプが必要であり、実際のオブジェクトは動的に割り当てられる必要があります。あなたの場合、構造体タイプは名前なしのままであり、変数tableは非動的に定義されています。したがって、コードを正しく再現したと仮定すると、「structhack」はここでは問題外です。

tableしたがって、コンパイルしても、使用可能なデータを含まない変数になってしまいます。この変数の唯一の使用法(静的ストレージ期間で宣言されている場合)は、&table式(「匿名構造体へのポインター」タイプのポインター)を介して一意のアドレス定数を生成することです。

宣言を「構造体ハック」に近いものに変える1つの方法は、そのtypedef前にを追加することです。

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

ただし、「構造体ハック」の「人間が生成した」構造体宣言には、通常、柔軟な配列宣言の前に他のデータフィールドが含まれます(これらがないと、通常の配列よりも「構造体ハック」を選択しても意味がありません)。

于 2012-12-25T06:50:11.250 に答える
1

これは、任意のサイズのメモリブロックをポインタ型にキャストし、最後の配列メンバーを可変長配列にするためのトリックです。おそらく標準ではありませんが、C配列は境界チェックされていないため、これは機能します。

これを示す非常に簡単な例を次に示します。

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

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

次に、このフィールドを使用して、count内の有効な要素の数を知ることができFoo*ます。前述のように、C配列は境界チェックされていないため、コンパイラーもランタイムも、foo->array読み取りまたは書き込みを試みたときにサイズが0の配列をキャッチしません。

于 2012-12-25T06:51:18.460 に答える
0

名前なしを定義したのは、struct実際には名前tableではなくオブジェクトstructです。

だから、あなたがこの宣言を持っているなら

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

または、

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

次に、これは可変長配列と呼ばれます(struct hackと呼ばれます)。

構造体の最後のメンバーである必要があるという制限があります。

詳細については、構造体ハックに関するこの記事を参照してください

于 2012-12-25T06:48:41.513 に答える