Как (вычислить) goto и longjmp в C ++? - PullRequest
12 голосов
/ 28 сентября 2011

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

Теперь я понимаю, что есть совершенно хорошие способы написания на C ++, но я собираюсь добиться личной победы, пытаясь сделать свой C ++Версия как ФОРТРАН-esque насколько это возможно.Что касается бонусных баллов, это может сэкономить мне время и силы при преобразовании кода.

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

На gotos:

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


Для longjmp:

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

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

Ответы [ 7 ]

7 голосов
/ 28 сентября 2011

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

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

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

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

4 голосов
/ 28 сентября 2011

Вы получите много ненависти по поводу использования 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.

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

3 голосов
/ 29 сентября 2011

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

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

3 голосов
/ 28 сентября 2011

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

Гото

longjmp

1 голос
/ 11 сентября 2012

Если я понимаю оригинальный вопрос, вопрос на самом деле интересный. Перефразируя вопрос (к тому, что я считаю эквивалентным вопросом): «Как вы делаете вычисленное на Фортране 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!

0 голосов
/ 28 сентября 2012

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

0 голосов
/ 28 сентября 2011

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

...