2016-11-29 7 views
4

私は構造体の配列へのポインタとその配列のサイズの2つの要素を含む構造体を静的に割り当てようとしています。ここでsizeof複合リテラル配列

は、コードの作業バージョンです:

#define ARRAY_SIZE(x) (sizeof((x))/sizeof((x)[0])) 

struct conf_element { 
     char *key; 
     enum conf_elem_type val_type; 
     void *val_p; 
     tok_t *(*fn_p)(const char *js, jsmntok_t *tok); 
}; 

struct conf_schema { 
     struct conf_element *conf_elems; 
     size_t size; 
}; 

struct conf_element conf_schema_antennae_elems[] = { 
     {"key1_nm", LEAF_INT, NULL, NULL}, 
     {"key2_nm", LEAF_INT, NULL, NULL} 
}; 

struct conf_schema conf_schema_antennae = { 
     conf_schema_antennae_elems, 
     ARRAY_SIZE(conf_schema_antennae_elems) 
}; 

しかし、ではなく、別々に配列を定義して、構造を定義する際に、その配列を参照して、私は順番に配列リテラルでポインタを初期化したいのですが私が信じるもののために構造定義にそれをすべて含むように増加する可読性:

struct conf_schema conf_schema_antennae = { 
     (struct conf_element []) { 
       {"key1_nm", LEAF_INT, NULL, NULL}, 
       {"key2_nm", LEAF_INT, NULL, NULL} 
     }, 
     /* the size of that^compound literal goes here */ 
}; 

は、それが自動的にコンパイル時にリテラルその配列のサイズを取得することは可能ですか? (または私は言語を乱用し、難しく、彼らは必要以上のものを作るのですか?)

EDIT:

#define S(arr) {arr, ARRAY_SIZE(arr)} 

struct conf_schema conf_schema_antennae = S((
     (struct conf_element []) { 
       {"key1_nm", LEAF_INT, NULL, NULL}, 
       {"key2_nm", LEAF_INT, NULL, NULL} 
     } 
)); 

#undef S 
+4

の可能性のある重複(http://stackoverflow.com/questions/35753494/can-i- reduce-a-long-array-initialization-to-a-short-initializer-list-in-c) – Olaf

+2

必要に応じて問題を[mcve]に分割すると、複製が終了します。私はまだ私の答えは、最も明確かつ容易な解決策だと思います。あなたの問題にただ取り入れてください。フィールドを変更しない場合は、 'const'修飾子(正しく!)を使用してください。 – Olaf

+1

ここで唯一の潜在的なトリックは、あなたが参照された答えで、Olafの記述のようなマクロへの引数として使用されるとき、(余分な)かっこで配列リテラルを囲む必要があるということです。かっこで囲まれた部分は、リテラル自体のカンマがマクロ引数の区切りとして扱われるのを防ぎます。 –

答えて

1
:同様の質問とジョン・ボリンジャーさんのコメントへのオラフの回答に基づいて、ここで私がなってしまったものだ

変数名が隠されているため、複合リテラル配列のサイズを知ることはできません。

また、struct conf_element *conf_elemsはポインタであり、ARRAY_SIZEマクロは実際の配列の長さを測定できません。

-gでコンパイルすると隠し変数の名前が表示されます。実行可能ファイルのデバッグ情報には、__compond_literal.###という名前の変数が表示されます。

回避策をお勧めします:実際にクライアントコードのサイズを知る必要がありますか? ない場合は、これを試してください:[?私はCで短い初期化子リストへの長い配列の初期化を減らすことができます]

struct conf_schema conf_schema_antennae = { 
     (struct conf_element []) { 
       {"key1_nm", LEAF_INT, NULL, NULL}, 
       {"key2_nm", LEAF_INT, NULL, NULL}, 
       {0, 0, 0, 0} /* Place holder for the end of the array */ 
     } 
}; 

void client_code() 
{ 
    struct conf_element *p_elems = conf_schema_antennae.conf_elems; 

    while (p_elems->key) 
    { 
    /* ... */ 
    p_elems++; 
    } 
} 
関連する問題