Подтвердить что ты не робот

Есть ли способ перебрать структуру с элементами разных типов в C?

Моя структура похожа на это

typedef struct {
  type1 thing;
  type2 thing2;
  ...
  typeN thingN;
} my_struct 

как перечислить дочерние элементы структуры в цикле, например while, или для?

4b9b3361

Ответ 1

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

//--- first describe the structure, the fields, their types and how to print them
#define X_FIELDS \
    X(int, field1, "%d") \
    X(int, field2, "%d") \
    X(char, field3, "%c") \
    X(char *, field4, "%s")

//--- define the structure, the X macro will be expanded once per field
typedef struct {
#define X(type, name, format) type name;
    X_FIELDS
#undef X
} mystruct;

void iterate(mystruct *aStruct)
{
//--- "iterate" over all the fields of the structure
#define X(type, name, format) \
         printf("mystruct.%s is "format"\n", #name, aStruct->name);
X_FIELDS
#undef X
}

//--- demonstrate
int main(int ac, char**av)
{
    mystruct a = { 0, 1, 'a', "hello"};
    iterate(&a);
    return 0;
}

Это напечатает:

mystruct.field1 is 0
mystruct.field2 is 1
mystruct.field3 is a
mystruct.field4 is hello

Вы также можете добавить имя функции, которая будет вызываться в X_FIELDS...

Ответ 2

Нет надежного способа перечисления элементов структуры, если точное содержание структуры не известно, и даже в этом случае вы должны быть осторожны с такими вещами, как выравнивание/добавление структуры.

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

Ответ 3

Поскольку вы планируете обрабатывать их в цикле, я предполагаю, что разные типы можно по крайней мере обрабатывать одинаково или иметь одинаковые размеры.

Если это так, ваш выбор будет зависеть от размера элементов. Если они все одинаковые, вы можете получить указатель на структуру, применить ее к одному из ваших типов и увеличивать ее до тех пор, пока не исчерпаете всю структуру.

PS: Действительно, это не очень безопасная практика. Эта ситуация намного лучше справилась с подходом OO, используя полиморфизм. В противном случае нет гарантий относительно выравнивания, как уже упоминалось ранее.

Ответ 4

Нет возможности перебирать элементы структуры на языке C независимо от того, имеют ли они одинаковый размер/тип или разные размеры/типы.

Ответ 5

Вы можете использовать арифметику Pointer для перемещения между элементами массива структур и NULL-указателем внутри одной из структур, чтобы остановить цикл. Например:

typedef struct {
    int   state;
    char *statename;
    int   count;
} job_states;

static job_states state2text[]= {
    {0, "STOPPED", 0},
    {10, "STARTING", 0},
    {20, "RUNNING", 0},
    {30, "BACKOFF", 0},
    {40, "STOPPING", 0},
    {100, "EXITED", 0},
    {200, "FATAL", 0},
    {1000, "UNKNOWN", 0},
    {0, NULL, 0}
};

job_states *js_p;

for(js_p = state2text; js_p->statename; js_p++) {
   if(js_p->state==state) js_p->count++;
}

Есть:

  1. js_p - указатель на начало массива структур с именем state2text.
  2. цикл для остановится, когда js_p-> statename станет равным NULL
  3. js_p++ перейти к следующей структуре в массиве структур