Reputation: 379
To simplify the question, if I have two structs like the following:
typedef struct test1_s {
uint16_t value1;
uint16_t b;
} test1_t;
typedef struct test2_s {
uint32_t value1;
uint32_t c;
} test2_t;
And I want a macro to work like this:
value = GET(x, value1);
but for different type of x, different process will be done for x->value1.
What I'm thinking of is that:
#define GET_test1_t_value1(x) x->value1 + 1
#define GET_test2_t_value1(x) x->value1 + 2
#define GET(x, field) GET_##typeof(x)##_##field(x)
But looks like the typeof can not work like this....
Is there any way to achieve that? It needs to be done in pure C. Thanks!
Upvotes: 0
Views: 435
Reputation: 40145
,sample in C11
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
typedef struct test1_s {
uint16_t value1;
uint16_t b;
} test1_t;
typedef struct test2_s {
uint32_t value1;
uint32_t c;
} test2_t;
#define GET(x, field) (x->field + _Generic(*x, test1_t: 1, test2_t:2))
int main(){
uint32_t value;
test1_t *x = &(test1_t){1,2};
test2_t *y = &(test2_t){3,4};
value = GET(x, value1);
printf("%" PRIu32 "\n", value);//2
value = GET(y, value1);
printf("%" PRIu32 "\n", value);//5
return 0;
}
Upvotes: 0
Reputation: 263237
typeof
is non-standard (it's an extension provided by gcc, and perhaps by some other compilers). And it doesn't expand to a string, so as you've already discovered you can't use in a macro definition like the one you're trying to do.
C11 added a new _Generic
keyword that permits something like what you want. It's used in a new kind of expression called a generic selection.
An example from the C standard:
#define cbrt(X) _Generic((X), \
long double: cbrtl, \
default: cbrt, \
float: cbrtf \
)(X)
(The default
association permits the use of cbrt
for integer types, which will be implicitly converted to double
.)
See section 6.5.1.1 of the N1570 draft of the 2011 ISO C standard.
Of course you can use this only if your compiler supports it. gcc first added support for _Generic
in release 4.9, which came out just a few days ago.
Upvotes: 2