web-dev-qa-db-ja.com

Cで異なるタイプの要素を持つ構造体をループする方法はありますか?

私の構造体はこのようなものです

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

whileやforなどのループで構造体の子を列挙する方法は?

20
drigoSkalWalker

何を達成したいかはわかりませんが、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で呼び出される関数の名前を追加することもできます。

41
philant

構造体の正確な内容がわからない限り、構造体のメンバーを列挙する安全な方法はありません。その場合でも、構造体の配置やパディングなどに注意する必要があります。

問題によっては、構造体の配列を使用する方が安全な場合があります。

3
Brian R. Bondy

サイズ/タイプが同じであるか、サイズ/タイプが異なるかに関係なく、C言語で構造体メンバーを反復処理する方法はありません。

1
AnT

それらをループで処理することを計画しているので、異なるタイプは少なくとも同じように扱うことができるか、同じようなサイズを持つことができると思います。

この場合、選択は要素のサイズによって異なります。それらがすべて同じである場合は、構造体へのポインターを取得し、それをタイプの1つにキャストして、構造体全体を「使い切る」までインクリメントできます。

PS:確かに、あまり安全な方法ではありません。この状況は、ポリモーフィズムを利用したOOアプローチを使用すると、はるかにうまく処理されます。それ以外の場合は、前述のように配置についての保証はありません。

1
danielkza