This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: Can we get C/C++ struct's member number, type, name, and format string?
- From: Mason <slash dot tmp at free dot fr>
- To: GCC help <gcc-help at gcc dot gnu dot org>
- Date: Tue, 24 Jan 2017 17:14:45 +0100
- Subject: Re: Can we get C/C++ struct's member number, type, name, and format string?
- Authentication-results: sourceware.org; auth=none
- References: <CAE99AOVK-kxtMRfiNJkPt1+BqDh4YHyDMo7FhsGSudU4-Uc2FQ@mail.gmail.com>
On 19/01/2017 03:19, hank fu wrote:
> Can we get C/C++ struct's member number, type, name, and format string?
>
> struct c_test_struct_type {
> int i_var;
> unsigned int ui_var;
> long l_var;
> unsigned long ul_var;
> }
>
> Is there one an operator provided by GCC to determine the member
> nubmer of this struct? For example, I hope to get 4 by calling
> '__struct_member_number__(struct c_test_struct_type)' .
>
> Is there one an operator provided by GCC to get the member name of
> this struct? For example, I hope to get string 'i_var' by calling
> '__struct_member_name__(struct c_test_struct_type, 0)'.
>
> Is there one an operator provided by GCC to get the member type of
> this struct? For example, I hope to get string 'int' by calling
> '__struct_member_type__(struct c_test_struct_type, 0)'.
Challenge accepted ^_^
$ cat struct.h
#ifdef GEN_STRUCT_DB
#define STRUCT(x) struct { const char *type, *name; } x ## db [] =
#define MEMBER(type, name) { #type, #name },
#else
#define STRUCT(x) struct x
#define MEMBER(type, name) type name;
#endif
STRUCT(foo)
{
MEMBER(int, i_var)
MEMBER(unsigned int, ui_var)
MEMBER(long, l_var)
MEMBER(unsigned long, ul_var)
};
#undef STRUCT
#undef MEMBER
$ cat main.c
#include "struct.h"
#define GEN_STRUCT_DB
#include "struct.h"
#define MEMBER_COUNT(x) (sizeof x ## db / sizeof * x ## db)
#define MEMBER_TYPE(x, i) x ## db [i].type
#define MEMBER_NAME(x, i) x ## db [i].name
#include <stdio.h>
int main(void)
{
unsigned i;
struct foo bar = { 12, 34, 56, 78 };
for (i = 0; i < MEMBER_COUNT(foo); ++i)
printf("TYPE=%s NAME=%s\n", MEMBER_TYPE(foo, i), MEMBER_NAME(foo, i));
return bar.i_var;
}
$ gcc -Wall -Wextra -std=c89 -pedantic -O2 main.c
$ ./a.out
TYPE=int NAME=i_var
TYPE=unsigned int NAME=ui_var
TYPE=long NAME=l_var
TYPE=unsigned long NAME=ul_var
I know that's not what you had in mind, but I like to find ways
to (ab)use the preprocessor ;-)
Regards.