Comment stocker des étiquettes goto dans un tableau puis y accéder?

Je veux déclarer un tableau de “jumplabels”.

Ensuite, je veux sauter à un “jumplabel” dans ce tableau.

Mais je n’ai aucune idée de comment faire cela.

Cela devrait ressembler au code suivant:

function() { "gotolabel" s[3]; s[0] = s0; s[1] = s1; s[2] = s2; s0: .... goto s[v]; s1: .... goto s[v]; s2: .... goto s[v]; } 

Quelqu’un a-t-il une idée de la manière de procéder?

C’est possible avec la fonctionnalité GCC appelée ” étiquettes en tant que valeurs “.

 void *s[3] = {&&s0, &&s1, &&s2}; if (n >= 0 && n <=2) goto *s[n]; s0: ... s1: ... s2: ... 

Cela ne fonctionne qu'avec GCC!

goto besoin d’une étiquette au moment de la compilation.

D’après cet exemple, il semble que vous mettiez en place une sorte de machine à états. Le plus souvent, ils sont implémentés en tant que construction switch-case:

 while (!finished) switch (state) { case s0: /* ... */ state = newstate; break; /* ... */ } 

Si vous en avez besoin pour être plus dynamic, utilisez un tableau de pointeurs de fonction.

Il n’y a pas de moyen direct pour stocker les adresses de code auxquelles accéder en C. Pourquoi utiliser switch?

 #define jump(x) do{ label=x; goto jump_target; }while(0) int label=START; jump_target: switch(label) { case START: /* ... */ case LABEL_A: /* ... */ } 

Vous pouvez trouver un code similaire produit par chaque générateur d’parsingur / parsingur d’état sans stack. Un tel code n’est pas facile à suivre, donc à moins qu’il ne soit généré par un code ou que votre problème soit décrit plus facilement par la machine à états, je vous recommande de ne pas le faire.

Pourriez-vous utiliser des pointeurs de fonction au lieu de goto?

De cette façon, vous pouvez créer un tableau de fonctions à appeler et appeler la fonction appropriée.

En clair C, cela n’est pas possible à ma connaissance. Il existe cependant une extension dans le compilateur GCC, documentée ici , qui rend cela possible.

L’extension introduit le nouvel opérateur && , qui prend l’adresse d’une étiquette, qui peut ensuite être utilisée avec l’ goto .

C’est à quoi servent les instructions de switch .

 switch (var) { case 0: /* ... */ break; case 1: /* ... */ break; default: /* ... */ break; /* not necessary here */ } 

Notez que ce n’est pas nécessairement traduit en table de saut par le compilateur.

Si vous voulez vraiment construire la table de saut vous-même, vous pouvez utiliser un tableau de pointeurs de fonction.

Vous voudrez peut-être regarder setjmp / longjmp.

Vous ne pouvez pas le faire avec un goto – les étiquettes doivent être des identifiants, pas des variables ou des constantes. Je ne vois pas pourquoi vous ne voudriez pas utiliser un interrupteur ici – il sera probablement tout aussi efficace, si c’est ce qui vous préoccupe.

Pour une réponse simple, au lieu d’obliger les compilateurs à faire des choses vraiment stupides, apprenez de bonnes pratiques de programmation.

Tokenizer? Cela ressemble à ce que gperf était fait. Non vraiment, jetez un coup d’oeil.

L’optimisation des compilateurs (y compris GCC) comstackra une instruction switch dans une table de saut (la rendant exactement aussi vite que ce que vous essayez de construire) SI les conditions suivantes sont remplies:

Vos cas de commutation (numéros d’état) commencent à zéro.

Vos cas de commutation augmentent ssortingctement.

Vous ne sautez aucun entier dans vos cas de commutation.

Il y a suffisamment de cas pour qu’une table de saut soit réellement plus rapide (une douzaine de comparaisons et résultats dans la méthode de vérification de chaque cas pour traiter des instructions switch est en réalité plus rapide qu’une table de saut.)

Cela a l’avantage de vous permettre d’écrire votre code en C standard au lieu de vous appuyer sur une extension du compilateur. Cela fonctionnera tout aussi vite dans GCC. Cela fonctionnera aussi rapidement avec la plupart des compilateurs d’optimisation (je sais que le compilateur Intel le fait; je ne suis pas sûr des produits Microsoft). Et cela fonctionnera, bien que plus lentement, sur n’importe quel compilateur.