私が正しく理解していれば、元の質問の核心は、構造体を反復処理する方法です。要するに、Jerry Coffin がコメントで指摘したように、これは実行できません。その理由を説明してから、次善の策を講じる方法を説明しようと思います。
構造体は、その構造を説明するメタデータなしで、モノリシックなデータとしてメモリに格納されます。たとえば、次の構造です。
struct Foo {
char a;
char b;
char c;
int i;
}
Foo f = {'x', 'y', 'z', 122};
次のように、16 進数表記を使用してメモリ内で表すことができます。
78 79 7A FF 7A 00 00 00
ここで、最初の 3 バイトには char フィールドが含まれ、4 番目はパディングに使用されるランダムな値であり、次の 4 バイトは整数 122 のリトル エンディアン表現です。このレイアウトは、コンパイラやシステムによって異なります。つまり、バイナリ表現では、データが何であるか、または個々のフィールドがどこに格納されているかはわかりません。
では、コンパイラは構造体のフィールドにどのようにアクセスするのでしょうか? コード
char c = f.c;
のような命令に変換されます
COPY BYTE FROM ([address of f] + 2) TO [address of c]
つまり、コンパイラはフィールドのリテラル オフセットをコードにエンコードします。繰り返しますが、これは役に立ちません。
したがって、構造に自分で注釈を付ける必要があります。これは、構造内に情報を追加して一種のキー値ストアにするか、2 つ目の構造を追加することで実現できます。元の構造を変更したくない場合は、2 つ目の構造を使用することをお勧めします。
私はあなたの構造体がint、charなどの基本的な型だけを保持していると仮定しています.構造体の他のクラスが複雑な場合は、ToString()メソッドをそれらの基本クラスに追加してそのメソッドを呼び出すことをお勧めします-それがC#とジャバやろ。
Foo tmp;
#define FIELD_OFFSET(f) ((char*)&(tmp.f) - (char*)&tmp)
enum FieldType { INT_FIELD, CHAR_FIELD, OBJECT_FIELD };
struct StructMeta {
FieldType type;
size_t offset;
};
StructMeta[] metadata = {
{CHAR_FIELD, FIELD_OFFSET(a)},
{CHAR_FIELD, FIELD_OFFSET(b)},
{CHAR_FIELD, FIELD_OFFSET(c)},
{INT_FIELD, FIELD_OFFSET(i)},
{OBJECT_FIELD, FIELD_OFFSET(o)},
}
void RenderStruct(Foo* f)
{
for (int i = 0; i < sizeof(metadata)/sizeof(StructMeta); i++)
{
switch (metadata[i].type)
{
case CHAR_FIELD:
char c = *((char*)f + metadata[i].offset);
// render c
break;
case INT_FIELD:
int i = *(int*)((char*)f + metadata[i].offset);
// render i
break;
case OBJECT_FIELD:
Object* o = (object*)((char*)f + metadata[i].offset);
const char* s = o->ToString();
// render s
break;
}
}
}
注: すべてのポインター演算は (char*) ポインターで実行して、オフセットがバイトとして解釈されるようにする必要があります。