Проблема в том, что case
ветви switch
ожидают постоянного значения. В частности, константа, известная во время компиляции 1004 *. Адрес строк не известен во время компиляции - компоновщик знает адрес, но даже не конечный адрес. Я думаю, что окончательный, перемещенный адрес доступен только во время выполнения.
Вы можете упростить вашу задачу до
void f() {
int x[*(int*)"x"];
}
Это приводит к той же ошибке, поскольку адрес литерала "x"
не известен во время компиляции. Это отличается от, например,
void f() {
int x[sizeof("x")];
}
Поскольку компилятор знает размер указателя (4 байта в 32-битных сборках).
Теперь, как исправить вашу проблему? Две вещи приходят мне на ум:
Не делайте поле 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" );
}
/* 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;
}
}
С этим, ваш оригинальный код может просто сделать:
void f( struct MyStruct *s ) {
s->printType( s );
}
Таким образом, вы централизуете проверку типа в одном месте, вместо того, чтобы загромождать свой код большим количеством switch
операторов.