Reputation: 3439
I have a constant lookup table
static const uint32_t lut [] = {0, 20, 100, 350, 560};
I have a struct
typedef struct {
uint32_t value;
const char * name;
} strct_t;
And I would like to create global constant instance of that struct
const struct_t def_myname = {
.value = lut[DEF_MYNAME_ID],
.name = "myname",
};
but I need to define DEF_MYNAME_ID
in other place, so I have this in some header file
#define DEF_MYNAME_ID 3
This can't compile, because of this error initializer element is not constant
There are multiple questions in stackoverflow asking what to do with initializer element is not constant
, but none covers my needs.
Is there a way how to do this? For example by defining lut
as macro? I don't need it in other place.
Is there something like
#define LUT(a) ...
usabele as const initializer?
Upvotes: 0
Views: 777
Reputation: 2967
Sure, macros can do that. This is actually a safer code, if you pick an index out of range, it won't compile.
First we define our dictionary
#define _val0 0
#define _val1 20
#define _val2 100
#define _val3 350
#define _val4 560
Now we need a PRIMITIVE_CAT
to force expansion of the argument of the macro LUT
.
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
And finaly, the LUT
.
#define LUT(X) PRIMITIVE_CAT(_val, X)
Now your code.
#define DEF_MYNAME_ID 3
const struct_t def_myname = {
.value = LUT(DEF_MYNAME_ID),
.name = "myname",
};
Upvotes: 1
Reputation: 361
I think you're mostly out of luck, at least with plain C, as even the following wouldn't compile as a static initializer:
int v = ((uint32_t[]) { 10, 20, 30, 40, 50 })[3];
FWIW, this would be fine:
static const uint32_t *pv = lut + DEF_MYNAME_ID;
as would be this (essentially the same):
static const uint32_t *pv = &(lut[DEF_MYNAME_ID]);
Also, in C++, your whole case would be fine as given.
Upvotes: 0