Как (вычислить) goto и longjmp в C++?

Я обычно не пишу код на C++, но мой странный друг-компаньон устал от просмотра моих замечательных программ на Фортране и предложил мне переписать одну из них на C++, так как ему больше нравятся мои C++-коды. (Мы ставим деньги здесь.) Точные условия заключаются в том, что они должны быть скомпилированы в современном компиляторе C++. Может быть, он ненавидит хороший conio.h - я не знаю.

Теперь я понимаю, что есть совершенно хорошие способы написания на C++, но я собираюсь добиться личной победы, пытаясь сделать мою версию C++ максимально приближенной к FORTRAN. Что касается бонусных баллов, это может сэкономить мне время и силы при преобразовании кода.

ТАК! Это подводит меня к следующим связанным запросам:

На gotos:

  1. Как вы работаете Goto?
  2. Каковы ограничения на gotos в C++?
  3. Есть какие-либо опасения по поводу объема? (Я собираюсь попытаться охватить как можно больше, но вы никогда не знаете.)
  4. Если я использую расширение GCC для перехода к массиву пустых указателей, есть ли какие-либо новые опасения по поводу неопределенного поведения и т. Д.?


На longjmp:

  1. Как бы вы безопасно использовали longjmp?
  2. Каковы ограничения на longjmps в C++?
  3. Что это делает с целью?
  4. Есть ли какие-то особые моменты, когда кажется, что longjmp должен быть безопасным, но на самом деле я не должен остерегаться этого?
  5. Как бы я смоделировал вычисленное goto с longjmp?
  6. Есть ли ощутимое преимущество использования longjmp по сравнению с goto, если в моей программе есть только одна функция?

Прямо сейчас моя главная задача состоит в том, чтобы заставить компьютер работать для этого. Похоже, что я, вероятно, буду использовать longjmp для этой работы, потому что массив указателей void не является частью стандарта C++, а является специфическим расширением GCC.

7 ответов

Я укушу и возьму понижение.

Я серьезно сомневаюсь, что ваш друг найдет, что Fortran, написанный на C++, легче читать (что вы получите, если значительно используете goto и longjmp) для чтения, и ему может даже сложнее следовать. Язык C++ довольно отличается от Fortran, и я действительно не думаю, что вы должны пытаться выполнить прямое преобразование из Fortran в C++. Это только усложнит поддержку C++, и вы могли бы остаться с существующей кодовой базой.

goto: Вы создали ярлык (my_label:), а затем используйте команду goto goto my_label; что приведет к выполнению потока вашей программы в операторе после перехода. Вы не можете перепрыгнуть через инициализацию переменной или между функциями. Вы не можете создать массив goto цели, но вы можете создать массив указателей на объекты или функции для перехода.

longjmp: Нет причин предпочитать longjmp над goto если у вас есть только одна функция. Но если у вас есть только одна функция, опять же, вы действительно не пишете на C++, и в конечном итоге вам будет лучше, если вы просто будете поддерживать свой Фортран.

Вы получите много ненависти об использовании goto совсем. Обычно я прыгаю прямо на подножку, но в данном конкретном случае это звучит для меня больше как код-гольф. Итак, поехали.

использование goto переместить указатель инструкции на "метку" в вашем коде, которая является идентификатором C++, за которым следует двоеточие. Вот простой пример работающей программы:

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

using namespace std;

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

}

В этом случае, step: это ярлык.

Есть опасения по поводу контекста.

  • Ты можешь только goto на метку в текущей функции.
  • Если твой goto пропускает инициализацию переменной, вы можете вызвать неопределенное поведение (код, который будет компилироваться, но вы не можете точно сказать, что он на самом деле будет делать).
  • Ты не можешь goto в к try блок или catch обработчик. Тем не менее, вы можете goto из try блок.

Вы можете "перейти" с помощью указателей и т. Д., Если другие проблемы будут выполнены. Если рассматриваемый указатель находится в области видимости на сайте вызова и в области видимости на сайте филиала, нет проблем.

Я думаю, что эта ссылка содержит большую часть информации, которую вы ищете.

идти к

longjmp

вычисленный goto -> switch

На самом деле они разделяют (распространенную, но не универсальную) базовую реализацию в виде таблицы переходов.

Если я понимаю оригинальный вопрос, вопрос на самом деле интересный. Перефразируя вопрос (к тому, что я считаю эквивалентным вопросом): "Как вы делаете вычисляемый на Фортране goto в C?"

Для начала нам нужно узнать, что такое вычисляемый переход: Вот ссылка на одно объяснение: http://h21007.www2.hp.com/portal/download/files/unprot/fortran/docs/lrm/lrm0124.htm.

Примером вычисленного GOTO является:

    GO TO (12,24,36), INDEX

Где 12, 24 и 36 - номера выписок. (Метки языка C могут служить эквивалентом, но это не единственное, что может быть эквивалентом.)

И где INDEX является переменной, но может быть результатом формулы.

Вот один способ (но не единственный) сделать то же самое в 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;
}

В этом конкретном примере мы видим, что вам не нужно C gotos для реализации вычисляемого goto на FORTRAN!

Longjmp может вывести вас из обработчика сигнала, что может быть неплохо - и это добавит некоторую путаницу, так как он не будет сбрасывать автоматические (основанные на стеке) переменные в функции, к которой он долго переходит, определенной до строки setjmp.:)

Существует расширение GCC, называемое Labels as Values, которое поможет вам написать код для игры в гольф, что, в сущности, даст вам расчетное значение. Конечно, вы можете создавать ярлыки автоматически. Вам, вероятно, потребуется сделать это, так как вы не можете знать, сколько байтов машинного кода сгенерирует каждая строка.

Другие вопросы по тегам