问题在于
switch
语句的
case
分支需要一个常量值。特别地,需要在
编译时就已知的常量值。字符串的地址在编译时是不知道的 - 链接器知道地址,但甚至最终地址也不确定。我认为最终重定位后的地址只有在运行时才能获得。
你可以将问题简化为:
void f() {
int x[*(int*)"x"];
}
这会产生相同的错误,因为编译时不知道"x"
字面量的地址。这与例如...不同。
void f() {
int x[sizeof("x")];
}
由于编译器知道指针的大小(32位构建中为4个字节)。
现在,如何解决您的问题?我想到了两件事:
不要将id
字段设置为字符串,而是设置为整数,然后在case
语句中使用常量列表。
我怀疑您需要在多个地方执行像这样的switch
,因此我的另一个建议是:首先不要使用switch
根据结构的类型执行代码。相反,结构可以提供函数指针,可以调用该指针来执行正确的printf
调用。在创建结构时,将函数指针设置为正确的函数。
这里是说明第二个想法的代码草图:
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" );
}
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;
}
}
有了这个,你的原始代码只需要执行以下操作:
void f( struct MyStruct *s ) {
s->printType( s );
}
这样,您可以将类型检查集中在一个地方,而不是在代码中杂乱无章地使用大量的switch
语句。