Reputation: 1351
I am writing a program which was a struct
with a need to store information on what type it's holding. The data is represented inside the the struct as a pointer to void. A short example of what I mean:
#include <stdio.h>
struct foo {
void *data;
char *type;
};
int main() {
struct foo bar = {{'a', 'b', 'c'}, "char"};
printf("%s\n", (STRING_TO_TYPE(bar.type))bar.data);
return 0;
}
I need an implementation of the STRING_TO_TYPE
macro that will replace "char"
with char
. All of this can be evaluated at compile time for the needs of my program.
What I want to do is hold an object of any type, so using an enum
or checking for string equality will not work.
Upvotes: 0
Views: 70
Reputation: 1183
Short answer: it is not possible. Not your way. Macros can produce tokens (keywords, if you like), but cannot convert strings to them.
That said, if the thing you are after is really
struct
with a "type" of its void *
somewhere in the code,struct
's name,then you will most likely end up with typeof
. It is a GNU extension, so it will only work in GCC, but it works.
In the example code here, you define your struct
of a certain "type" with the MYSTRUCT macro and get the type using the TYPE macro. The __COUNTER__ predefined macro prevents type redefining (each struct
is its own type, see gcc -E
) and three macro levels for MYSTRUCT are there for proper stringification of it.
#include <stdio.h>
#define TYPE(x) typeof(x.type)
#define MYSTRUCT(name, type) MYSTRUCT_INTER(name, type, __COUNTER__)
#define MYSTRUCT_INTER(name, type, counter) MYSTRUCT_RAW(name, type, counter)
#define MYSTRUCT_RAW(xName, xType, xCounter) \
struct mystruct_## xCounter { \
void * data; \
xType type; \
} xName
int main(void) {
MYSTRUCT(foo, int);
foo.data = (void *)42;
TYPE(foo) tmp = foo.data; /* <-- Here, tmp is an int */
printf("%d\n", tmp);
MYSTRUCT(bar, int*);
bar.data = &tmp;
TYPE(bar) tmp2 = bar.data; /* <-- Here, tmp2 is an int* */
printf("%p\n", tmp2);
MYSTRUCT(baz, char*);
baz.data = "Hello world";
printf("%s\n", (TYPE(baz))baz.data);
/* ^Expands to (char *) baz.data */
}
Note that I still need to know the struct
's "type" to determine printf()
's format code, but solving this was not asked.
Don't forget to compile with -std=gnu**
(you need it for typeof
)
Upvotes: 1