Reputation: 920
I want to initialize different union member depending if a macro expression is a constant or a variable.
So far I've found GCC extension __builtin_constant_p()
which evaluates an expression and returns 1 if it is a constant and 0 otherwise. Which is exactly what I need. However I have yet to found a way how to initialize different union members based on this information.
Below is the code example:
#define TOKEN 10
typedef union
{
void* pv_variable;
int literal;
} foo_t;
foo_t test_array[] =
{
{.literal = 500},
{.pv_variable = NULL}
// Below doesnt work. How to make it work??
//
// {(TOKEN == 10) ? (.literal) : (.pv_variable) = 10},
// {__builtin_choose_expr(__builtin_constant_p(TOKEN), .literal = 10, .pv_variable = NULL)},
// {. ## __builtin_choose_expr(__builtin_constant_p(TOKEN), literal, pv_variable) = 10},
};
EDIT: Clarification on what I want to accomplish is detailed below.
#define INIT_UNION(val) /* TODO: */
#define SOME_VARIABLE some_variable
#define SOME_CONSTANT 10
int some_variable = 20;
typedef union
{
void* pv_variable;
int literal;
} foo_t;
foo_t test_array[] =
{
INIT_UNION(SOME_CONSTANT), /* should produce: {.literal = 10} */
INIT_UNION(SOME_VARIABLE) /* should produce: {.pv_variable = &some_variable} */
};
Upvotes: 1
Views: 114
Reputation: 835
Your first idea was pretty close:
#define TOKEN 10
typedef union foo_u
{
void* pv_variable;
int literal;
} foo_t;
#define INIT_FOO_T(val) (__builtin_constant_p(val) ? (foo_t) {.literal = val} : (foo_t) {.pv_variable = val})
foo_t test_array[] =
{
{.literal = 500},
{.pv_variable = NULL},
INIT_FOO_T(TOKEN)
};
Unfortunately you can use #if
inside a #define
, so this is the only way.
Maybe instead of:
#define INIT_FOO_T(val) (__builtin_constant_p(val) ? (foo_t) {.literal = val}
you mean:
#define INIT_FOO_T(val) (__builtin_constant_p(val) ? (foo_t) {.literal = &val}
this would make more sense but requires a different approach (it won't work anymore).
EDIT: you want the second case
#if __builtin_constant_p(TOKEN)
foo_t test_array[] =
{
{.literal = 500},
{.pv_variable = NULL},
#if __builtin_constant_p(TOKEN)
{.literal = TOKEN},
#else
{.pv_variable = &TOKEN},
#endif
};
Unfortunately I don't know how you can build a macro to do this for you.
Upvotes: 1