pour élaborer davantage sur Jerry's answer et d'autres
Vu:
int x=1;
switch (i) {
case 1: x=6; break;
case 2: x++;
// Fall through
case 3: x+=7; break;
}
vous pourriez avoir quelque chose comme ce qui suit:
int f1() {return 6;}
int f2() {return 1+f3();}
int f3() {return 8;}
Le compilateur peut utiliser une table de saut à l'index {f1, f2, f3}
Le compilateur peut faire inline lors de la création de la table ayant f1, f2, f3
de réglage x
directement à 6,9,8
Mais si vous avez écrit les fonctions et rouliez votre propre table de saut, f1,f2,f3
pourrait être partout, mais le compilateur saura les mettre près de la switch
créer beaucoup mieux localité de code que vous pourriez.
Notez que dans de nombreux cas, le compilateur génère un garde pour vérifier si i
est à portée (ou gérer la default
) et si vous êtes sûr qu'il est toujours l'un des cas, vous pouvez sauter cette
la chose intéressante est que pour moins d'un petit nombre de cas, et sous différents drapeaux du compilateur (dépend du compilateur) le switch
ne serait pas utiliser une table, mais se contentait de faire ifs, semblable à:
if (i==1) x=f1();
else if (i==2) x=f2();
else if (i==3) x=f3();
ou il pourrait optimiser ceci (où les tests simples sont une instruction) à:
x=(i==1) ? f1()
: (i==2) ? f2()
: (i==3) ? f3()
: x;
Le meilleur conseil est de regarder l'ensemble généré pour voir ce que le compilateur a fait à votre code sur votre architecture, g ++ sur Linux/Intel va générer quelque chose comme ce qui suit, s'il y a une table de saut
(note que je devais aller à 5 case
déclarations pour forcer la table de saut, il a utilisé ifs dessous de ce nombre de case
déclarations)
Notez que les petits trous seront dans la table de saut pour faire le default
int foo(int i)
{
int x=1;
switch (i) {
case 1: x=6; break;
case 2: x++;
// Fall through
case 3: x+=7; break;
case 4: x+=2; break;
case 5: x+=9; break;
}
return x;
}
générerait le code assembleur suivant (// commentaires sont les miens):
cmp edi, 5 //make sure it is not over 5
ja .L2 //jump to default case
mov edi, edi
jmp [QWORD PTR .L4[0+rdi*8]] // use the jump table at label L4:
.L4:
.quad .L2 // if i=0, set x=1 (default)
.quad .L9 // f1() see below
.quad .L10 // f2() see below
.quad .L6 // f3() see below
.quad .L7 // f4() see below
.quad .L8 // f5() see below
.L10:
mov eax, 9 // x=9
ret
.L9:
mov eax, 6 // x=6
ret
.L8:
mov eax, 10 // x=10
ret
.L6:
mov eax, 8 // x=8
ret
.L7:
mov eax, 3 // x=3
ret
.L2:
mov eax, 1 // default, x was 1, noop is: x=1
ret
Habituellement, un "dictionnaire" est la même chose qu'une hashtable. –