The issue is that the case
branches of a switch
expect a constant value. In particular, a constant which is known at compile time. The address of strings isn't known at compile time - the linker knows the address, but not even the final address. I think the final, relocated, address is only available at runtime.
You can simplify your problem to
void f() {
int x[*(int*)"x"];
}
This yields the same error, since the address of the "x"
literal is not known at compile time. This is different from e.g.
void f() {
int x[sizeof("x")];
}
Since the compiler knows the size of the pointer (4 bytes in 32bit builds).
Now, how to fix your problem? Two things come to my mind:
Don't make the id
field a string but an integer and then use a list of constants in your case
statements.
I suspect that you will need to do a switch
like this in multiple places, so my other suggestion is: don't use a switch
in the first place to execute code depending on the type of the structure. Instead, the structure could offer a function pointer which can be called to do the right printf
call. At the time the struct is created, the function pointer is set to the correct function.
Here's a code sketch illustrating the second idea:
struct MyStructure {
const char *id;
void (*printType)(struct MyStructure *, void);
void (*doThat)(struct MyStructure *, int arg, int arg);
/* ... */
};
static void printSqrtType( struct MyStructure * ) {
printf( "its a sqrt\n" );
}
static void printLog2Type( struct MyStructure * ) {
printf( "its a log2\n" );
}
static void printLog2Type( struct MyStructure * ) {
printf( "works somehow, but unreadable\n" );
}
/* Initializes the function pointers in the structure depending on the id. */
void setupVTable( struct MyStructure *s ) {
if ( !strcmp( s->id, "sqrt" ) ) {
s->printType = printSqrtType;
} else if ( !strcmp( s->id, "log2" ) ) {
s->printType = printLog2Type;
} else {
s->printType = printUnreadableType;
}
}
With this in place, your original code can just do:
void f( struct MyStruct *s ) {
s->printType( s );
}
That way, you centralize the type check in a single place instead of cluttering your code with a lot of switch
statements.