Размер составного литерального массива

Я пытаюсь статически выделить некоторые структуры, каждая из которых содержит два члена: указатель на массив структур и размер этого массива.

Вот рабочая версия кода:

#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 */
};

Можно ли автоматически получить размер этого массива литерала во время компиляции? (Или я злоупотребляю языком и усложняю ситуацию?)

РЕДАКТИРОВАТЬ: Основываясь на ответе Олафа на аналогичный вопрос и комментарии Джона Боллинджера, вот что я закончил:

#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

1 ответ

Вы не можете знать размер составного литерального массива, потому что имя его переменной скрыто.

Также struct conf_element *conf_elems это указатель и макрос ARRAY_SIZE не может измерить длину реального массива.

Вы можете увидеть имя скрытой переменной, если скомпилировано с -g, В отладочной информации исполняемого файла будет показана переменная с именем __compond_literal.###,

Я предлагаю вам обходной путь: вам действительно нужно знать его размер в клиентском коде? Если нет, попробуйте это:

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++;
    }
}
Другие вопросы по тегам