Comment (computed) goto et longjmp en C++?

Je n'ai pas l'habitude de coder C++, mais un ami de SCI étrange de moi en a eu marre de regarder mes merveilleux programmes FORTRAN et m'a mis au défi de réécrire l'un d'eux en C++, puisqu'il préfère mes codes C++. (Nous sommes en pariant de l'argent ici.) Les termes exacts étant qu'il doit être compilable dans un compilateur C++ moderne. Peut-être qu'il déteste un bon conio.h - je ne sais pas.

maintenant je me rends compte qu'il y a parfaitement de bonnes façons d'écrire en C++, mais je vais chercher une victoire personnelle ici en essayant de faire ma version C++ comme FORTRAN-esque que possible. Pour les points bonus, cela pourrait me faire gagner du temps et de l'effort lorsque je suis en train de convertir du code.

alors! Cela m'amène à la suite de requêtes associées:

Sur gotos:

  1. Comment fonctionne un goto?
  2. quelles sont les contraintes sur gotos en C++?
  3. des préoccupations au sujet de la portée? (Je vais essayer d'étendre la portée globale autant que possible, mais on ne sait jamais.)
  4. Si I utilisez L'extension GCC pour goto vers un tableau de pointeur de vide, y a-t-il de nouvelles préoccupations au sujet du comportement non défini, etc.?



Sur longjmp:

  1. comment utiliser un longjmp en toute sécurité?
  2. quelles sont les contraintes sur les longjmps en C++?
  3. Qu'est-ce que ça fait à scope?
  4. y a-t-il des moments spécifiques où il semble qu'un longjmp devrait être sûr mais en fait ce n'est pas que je devrais faire attention pour?
  5. comment simuler un goto calculé avec longjmp?
  6. y a-t-il un avantage tangible à utiliser longjmp par rapport à goto si je n'ai qu'une seule fonction dans mon programme?

en ce moment mon principal souci est de faire fonctionner un goto calculé pour cela. il semble que je vais probablement utiliser le longjmp pour faire fonctionner ceci parce qu'un tableau de pointeur de vide ne fait pas partie du standard C++ mais une extension spécifique au GCC.

12
demandé sur Code Maker 2011-09-28 22:53:29

7 réponses

je vais mordre et prendre le downvote.

je doute sérieusement que votre ami trouve Fortran écrit en C++ plus facile à lire (ce qui est effectivement ce que vous obtiendrez si vous utilisez goto et longjmp de manière significative) et il pourrait même trouver plus difficile à suivre. Le langage C++ est assez différent de Fortran et je ne pense vraiment pas que vous devriez tenter une conversion directe de Fortran en C++. Cela rendra juste le C++ plus difficile à maintenir et vous pourriez aussi bien rester avec votre existant codebase.

goto: Vous mettez en place un label (my_label:) et ensuite utiliser la commande goto goto my_label; ce qui causera l'exécution du flux de votre programme à l'instruction suivant le goto. Vous ne pouvez pas sauter de l'initialisation d'une variable ou d'une fonction. Vous ne pouvez pas créer un tableau de goto cibles, mais vous créer un tableau d'objet ou de pointeurs de fonction pour sauter.

longjmp: Il n'y a aucune raison de préférer longjmpgoto si vous avez une seule fonction. Mais si vous n'avez qu'une seule fonction, encore une fois, vous n'écrivez pas C++ et vous serez mieux à long terme tout en maintenant votre Fortran.

7
répondu Mark B 2011-09-28 19:31:28

Vous obtiendrez beaucoup de haterade sur l'utilisation de goto à tous. Normalement, je sauterais dans le train, mais dans ce cas précis, ça ressemble plus à du golf codé. Donc, ici vous allez.

Utiliser goto pour déplacer le pointeur d'instruction vers un "label" dans votre code, qui est un identifiant C++ suivi de deux points. Voici un exemple simple d'un programme de travail:

#include <iostream>
#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    int i = 0;
step:
    cout << "i = " << i;
    ++i;
    if( i < 10 )
        goto step;

}

Dans ce cas, step: est l'étiquette.

il y a des inquiétudes à propos de cadre.

  • Vous ne pouvez goto à une étiquette dans la fonction courante.
  • Si votre goto saute de l'initialisation d'une variable, vous pouvez évoquer Comportement Non Défini (Code qui va se compiler, mais vous ne pouvez pas dire avec certitude ce qu'il va réellement faire.).
  • Vous ne pouvez pas goto dans un try ou catch gestionnaire. Cependant, vous goto d'un try bloc.

vous "pouvez aller" avec des pointeurs etc à condition que les autres préoccupations soient satisfaites. Si le pointeur en question Est dans la portée à l'emplacement de l'appel et dans la portée à l'emplacement de la branche, aucun problème.

4
répondu John Dibling 2017-05-23 11:45:44

je pense que cette référence contient la plupart des informations que vous recherchez.

goto

longjmp

3
répondu ronag 2011-09-28 19:21:09

calculées goto-->switch

en réalité, ils partagent une implémentation (commune, mais pas universelle) sous-jacente comme une table de saut.

3
répondu dmckee 2011-09-28 23:02:16

si je comprends la question originale, la question est en fait intéressante. Reformuler la question (à ce que je pense être une question équivalente): "Comment faire un Goto Fortran calculé en C?"

tout d'abord, nous avons besoin de savoir ce qu'est un goto calculé: voici un lien vers une explication: http://h21007.www2.hp.com/portal/download/files/unprot/fortran/docs/lrm/lrm0124.htm.

un exemple de GOTO calculé est:

    GO TO (12,24,36), INDEX

Où 12, 24, et 36 sont des numéros de déclaration. (C les étiquettes de langue pourraient servir d'équivalent, mais ce n'est pas la seule chose qui pourrait être un équivalent.)

et où INDEX est une variable, mais pourrait être le résultat d'une formule.

Ici est une façon (mais pas la seule) de faire la même chose en C:

int SITU(int J, int K)
{
int raw_value = (J * 5) + K;

int index = (raw_value % 5) - 1;

return index;
}


int main(void)
{
int J = 5, K= 2;

// fortran computed goto statement: GO TO (320,330,340,350,360), SITU(J,K) + 1
switch (SITU(J,K) + 1)
{
case 0: // 320
    // code statement 320 goes here
    printf("Statement 320");
    break;
case 1: // 330
    // code statement 330 goes here
    printf("Statement 330");
    break;
case 2: // 340
    // code statement 340 goes here
    printf("Statement 340");
    break;
case 3: // 350
    // code statement 350 goes here
    printf("Statement 350");
    break;
case 4: // 360
    // code statement 360 goes here
    printf("Statement 360");
    break;
}

printf("\nPress Enter\n");
getchar();
return 0;
}

dans cet exemple particulier, nous voyons que vous n'avez pas besoin de C gotos pour implémenter un Goto Fortran calculé!

1
répondu Indinfer 2012-09-11 02:50:02

Longjmp peut vous sortir d'un gestionnaire de signal qui peut être agréable - et cela ajoutera une certaine confusion car il ne réinitialisera pas les variables automatiques (basées sur la pile) dans la fonction qu'il saute de long À défini avant la ligne setjmp. :)

0
répondu John Humphreys - w00te 2011-09-28 19:07:34

il y a une extension GCC appelée Étiquettes de Valeurs cela vous aidera à coder le golf, en vous donnant essentiellement Goto calculé. Vous pouvez générer les étiquettes automatiquement, bien sûr. Vous aurez probablement besoin de faire cela puisque vous ne pouvez pas savoir combien d'octets de code machine chaque ligne générera.

0
répondu Janus Troelsen 2012-09-27 20:18:33