Статически инициализированная структура self-reference - PullRequest
3 голосов
/ 17 ноября 2011

У меня есть простая структура, которая определяется следующим образом:

typedef struct { 
    int index;
    double* arrayToRead;
} my_struct;

Я хочу инициализировать массив структур, чтобы они стали примерно такими:

double decimals[2] = {1.0, 2.0};

my_struct[2] = {
    {0, &decimals[0]},
    {1, &decimals[1]}
};

Мне нужностатически инициализировать этот массив структур.

Можно ли статически инициализировать его при обращении к ранее определенному члену, например так:

my_struct[2] = {
    {0, &decimals[index]},
    {1, &decimals[index]}
};

Где «индекс» относится к значению индекса, определенного дляслева от "десятичных дробей"?

Ответы [ 4 ]

7 голосов
/ 17 ноября 2011

Если у вас современный компилятор C (он же C99), вы можете использовать P99 для развертывания кода.Что-то вроде

#define INIT_ELEMENT(NAME, X, I) [I] = { \
  .index = I,                            \
  .arraytoread = &decimals[I]            \
}
#define INIT_ELEMENTS(N) P99_FOR(, N, P00_SEQ, INIT_ELEMENT, P99_DUPL(N,))

, а затем

my_struct A[] = { INIT_ELEMENTS(2) };

должно расшириться до инициализатора по вашему вкусу.

(Здесь первый макрос определяет код, который должен повторяться, используя только I из своих аргументов, индекс вызова. Во втором макросе P00_SEQ означает, что это разделено запятой.)

5 голосов
/ 17 ноября 2011

Нет. *

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

#define DEFINE_ELEMENT(i) {(i), &decimals[(i)]}
my_struct m[2] = {
    DEFINE_ELEMENT(0),
    DEFINE_ELEMENT(1)
};
#undef DEFINE_ELEMENT


*Или "да", как указывает @Jens в своем ответе, для C99.
0 голосов
/ 17 ноября 2011

я думаю, что вам нужно дать имя для вашего нового массива

my_struct my_array[2] = {
  {0, &decimals[my_array[0].index]},
  {1, &decimals[my_array[1].index]}
};
0 голосов
/ 17 ноября 2011

Что это на небе? Это птица! Нет, это самолет! Нет, это человек, генерирующий код!

enter image description here

Или - с удаленным языком из щеки - я не знаю, что есть встроенная функция, которая поддерживает это, но вы всегда можете использовать внешний инструмент для написания кода инициализации для вас.


По сути, вы пишете скрипт на каком-то удобном языке, который выводит фрагмент кода переменного тока, определяющий структуру и объявляющий переменную с инициализацией в длинных руках, а затем используете функцию #include c-препроцессора для перетаскивания этого сгенерированного файла в ваш код.

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

cfile.o: cfile.c mystruct.c

my_struct.c:
        awk -f generate_my_struct.awk > my_struct.c
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...