Ecco una prova di concetto:
#include <stdio.h>
#include <string.h>
#define MEMBER(TYPE,NAME,MORE) TYPE NAME MORE
#define TSTRUCT(NAME,MEMBERS) \
typedef struct NAME { \
MEMBERS \
} NAME; \
const char* const NAME##_Members = #MEMBERS;
#define PRINT_STRUCT_MEMBERS(NAME) printStructMembers(NAME##_Members)
TSTRUCT(S,
MEMBER(int,x;,
MEMBER(void*,z[2];,
MEMBER(char,(*f)(char,char);,
MEMBER(char,y;,
)))));
void printStructMembers(const char* Members)
{
int level = 0;
int lastLevel = 0;
const char* p;
const char* pLastType = NULL;
const char* pLastTypeEnd = NULL;
for (p = Members; *p; p++)
{
if (strstr(p, "MEMBER(") == p)
{
p += 6; // strlen("MEMBER")
level++;
lastLevel = level;
pLastType = p + 1;
}
else if (*p == '(')
{
level++;
}
else if (*p == ')')
{
level--;
}
else if (*p == ',')
{
if (level == lastLevel)
{
if ((pLastType != NULL) && (pLastTypeEnd == NULL))
{
pLastTypeEnd = p;
}
}
}
else if (strstr(p, ";,") == p)
{
if ((pLastType != NULL) && (pLastTypeEnd != NULL))
{
const char* pp;
printf("[");
for (pp = pLastType; pp < pLastTypeEnd; pp++)
printf("%c", *pp); // print type
printf("] [");
for (pp = pLastTypeEnd + 1; pp < p; pp++)
printf("%c", *pp); // print name
printf("]\n");
}
pLastType = pLastTypeEnd = NULL;
}
}
}
char fadd(char a, char b)
{
return a + b;
}
S s =
{
1,
{ NULL, NULL },
&fadd,
'a'
};
int main(void)
{
PRINT_STRUCT_MEMBERS(S);
return 0;
}
Questo è il suo output:
[int] [x]
[void*] [z[2]]
[char] [(*f)(char,char)]
[char] [y]
Puoi migliorarlo per supportare meglio i tipi di membri più complessi e creare effettivamente un elenco di nomi dei membri.
fonte
2011-10-06 14:20:26
+1 Mostrami di più sull'ultimo paragrafo. – nc3b
@ nc3b Si utilizza una macro del compilatore 'DEFSTRUCT (int, x, float, y, char *, z)' o simili che crea la struttura precedente e inoltre emette 'char ** members = {" x "," y " , "z", NULL}; '. Se vuoi una macro meno complicata, puoi farlo in due invocazioni, come 'DEFSTRUCT (int, x)' e quindi 'DEFLIST (int, x)' (o con una macro che definisci per avere comportamenti diversi per ogni chiamata e quindi invoca due volte). – Borealid