Il problema è che i rami case
di un switch
prevedono un valore costante. In particolare, una costante nota al tempo di compilazione. L'indirizzo delle stringhe non è noto al momento della compilazione - il linker conosce l'indirizzo, ma nemmeno l'indirizzo finale. Penso che l'indirizzo finale, trasferito, sia disponibile solo in fase di esecuzione.
è possibile semplificare il problema per
void f() {
int x[*(int*)"x"];
}
Questo produce lo stesso errore, dal momento che l'indirizzo del "x"
letterale non è noto al momento della compilazione. Questo è diverso da ad es.
void f() {
int x[sizeof("x")];
}
Poiché il compilatore conosce la dimensione del puntatore (4 byte 32bit build).
Ora, come risolvere il problema? Due cose mi vengono in mente:
Non fare il campo id
una stringa, ma un intero e quindi utilizzare un elenco di costanti nei vostri case
dichiarazioni.
Ho il sospetto che sarà necessario fare un switch
come questo in più luoghi, quindi il mio altro suggerimento è: non utilizzare un switch
in primo luogo per eseguire codice a seconda del tipo di struttura. Invece, la struttura potrebbe offrire un puntatore a funzione che può essere chiamato per fare la giusta chiamata printf
. Al momento della creazione della struttura, il puntatore della funzione viene impostato sulla funzione corretta.
Ecco uno schizzo di codice che illustra la seconda 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;
}
}
Con questo in luogo, il codice originale può fare solo:
void f(struct MyStruct *s) {
s->printType(s);
}
questo modo, è centralizzare il controllo di tipo in un unico posto invece di ingombrare il codice con un sacco di dichiarazioni switch
.
È per C++ (come nel titolo della domanda) o per C99 (come nei tag)? Non sono sicuro che la risposta sia diversa tra i due, ma vedere due lingue diverse nella domanda senza una chiara motivazione è fonte di confusione. –
corretto il titolo –
Ora ci sono _two_ lingue nel titolo, una delle quali viene ripetuta nei tag. Ne deduciamo che non parli del C++, dopotutto? Perché è ancora nel titolo allora? –