goto

Поделись знанием:
(перенаправлено с «GOTO»)
Перейти к: навигация, поиск

goto (от англ. go to — «перейти на») — оператор безусловного перехода (перехода к определённой точке программы, обозначенной номером строки либо меткой) в некоторых языках программирования. В некоторых языках оператор безусловного перехода может иметь другое имя (например, jmp в языках ассемблера).





Функциональность

Как правило, оператор goto состоит из двух частей: собственно оператора и метки, указывающей целевую точку перехода в программе: goto метка. Метка, в зависимости от правил языка, может быть либо числом (как, например, в классическом Бейсике), либо идентификатором используемого языка программирования. Для меток-идентификаторов метка, как правило, ставится перед оператором, на который должен осуществляться переход, и отделяется от него двоеточием (метка:).

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

Распространение

Оператор goto имеется в таких языках, как Фортран, Алгол, Кобол, Бейсик, Си и C++, C#, D, Паскаль, Perl, Ада, PHP и многих других. Он присутствует также во всех языках ассемблера (обычно под названием jmp, jump или bra (от англ. branch — ветвь)). Свобода использования goto в разных языках различается. Если в ассемблерах или языках типа Фортрана он может применяться произвольно (допускается передача управления внутрь ветви условного оператора или внутрь тела цикла или процедуры), то в более высокоуровневых языках его использование ограничено: как правило, с помощью goto запрещено передавать управление между различными процедурами и функциями, внутрь выделенного блока операторов, между ветвями условного оператора и оператора множественного выбора.

goto отсутствует в некоторых языках высокого уровня (например, в Форт). В Паскаль goto первоначально включён не был, но недостаточность имеющихся языковых средств вынудила Никлауса Вирта его добавить. В более поздних своих языках Вирт всё же отказался от goto: этого оператора нет ни в Модуле-2, ни в Обероне и Компонентном Паскале. В Java есть зарезервированное слово goto, но оно не несёт никаких функций — оператора безусловного перехода в языке нет (однако переход осуществить можно[1]). При этом в языке сохранились метки — они могут применяться для выхода из вложенных циклов операторами break и continue.

Критика

Оператор goto в языках высокого уровня является объектом критики, поскольку чрезмерное его применение приводит к созданию нечитаемого «спагетти-кода». Впервые эта точка зрения была отражена в статье Эдсгера Дейкстры «Доводы против оператора GOTO»,[2] который заметил, что качество программного кода обратно пропорционально количеству операторов goto в нём. Статья приобрела широкую известность как среди теоретиков, так и среди практиков программирования, в результате чего взгляды на использование оператора goto были существенно пересмотрены. В своей следующей работе Дейкстра обосновал тот факт, что для кода без goto намного легче проверить формальную корректность.

Код с goto трудно форматировать, так как он может нарушать иерархичность выполнения (парадигму структурного программирования) и потому отступы, призванные отображать структуру программы, не всегда могут быть выставлены правильно. goto также мешает оптимизации компиляторами управляющих структур.[3]

Некоторые способы применения goto могут создавать проблемы с логикой исполнения программы:

  • Если некоторая переменная инициализируется (получает значение) в одном месте и потом используется далее, то переход в точку после инициализации, но до использования, приведёт к тому, что будет использовано значение, которое находилось в памяти, выделенной под переменную, до момента выделения (и которое, как правило, является произвольным и случайным).
  • Передача управления внутрь тела цикла приводит к пропуску кода инициализации цикла или первоначальной проверки условия. Аналогично, передача управления внутрь процедуры или функции приводит к пропуску её предисловия (пролога), в котором производится инициализация (выделение памяти под локальные переменные и т. п.).

Доводы против оператора goto оказались столь серьёзны, что в структурном программировании его стали рассматривать как крайне нежелательный. Это нашло отражение при проектировании новых языков программирования. Например, goto был запрещён в Java и Ruby. В ряде современных языков он всё же оставлен из соображений эффективности в тех редких случаях, когда применение goto оправданно. Так, goto сохранился в Аде — одном из наиболее продуманных с точки зрения архитектуры языков за всю историю.[4] Однако в тех современных языках высокого уровня, где этот оператор сохранился, на его использование, как правило, накладываются жёсткие ограничения, препятствующие использованию наиболее опасных методов его применения: например, запрещается передавать управление извне цикла, процедуры или функции внутрь. Стандарт языка C++ запрещает обход инициализации переменной с помощью goto.

Формально доказано (теорема Бёма — Якопини), что применение goto не является обязательным, то есть не существует такой программы с goto, которую нельзя было бы переписать без него с полным сохранением функциональности (однако, возможно, с потерей эффективности).

Оправданное применение

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

Главным критерием применимости goto является ненарушение используемой парадигмы программирования (в приведённых ниже примерах это структурное программирование), в противном случае результат чреват всевозможными побочными эффектами и труднообнаружимыми ошибками.

Выход из вложенных циклов

В некоторых языках нет операторов досрочного завершения цикла или они относятся только к тому из вложенных циклов, в котором расположены (например, break и continue в Си). Использование goto для выхода из нескольких вложенных циклов сразу в этом случае значительно упрощает код программы, избавляя от необходимости применения вспомогательных переменных-флагов и условных операторов.

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

Пример на языке Си++:

int matrix[n][m];
int value;
...
for(int i=0; i<n; i++)
  for (int j=0; j<m; j++)
    if (matrix[i][j] == value)
    {
      printf("value %d found in cell (%d,%d)\n",value,i,j);
      //act if found
      goto end_loop;
    }
printf("value %d not found\n",value);
//act if not found
end_loop: ;

Прямолинейный способ избавления от goto — создать дополнительную переменную-флаг, сигнализирующую, что надо выйти из внешнего цикла (после выхода из внутреннего по break) и обойти блок кода, выполняющийся, когда значение не найдено.

Без изменения структуры кода проблема решается, если команда break (или её аналог) позволяет выйти из нескольких вложенных блоков сразу, как в Java или Ада. Пример на языке Java:

int[][] matrix;
int value;
...
outer: {
  for(int i=0; i<n; i++)
    for (int j=0; j<m; j++)
      if (matrix[i][j] == value)
      {
        System.out.println("value " + value + " found in cell (" + i + "," + j + ")");
        break outer;
      }
  System.out.println("value " + value + " not found");
}

Наиболее элегантный способ выйти из вложенного цикла предлагает язык PHP[5]. После команды break можно указать количество циклов, которые нужно покинуть:

for($i=0; $i < $Imax; ++$i) {
   // ...
   for($j=0; $j < $Jmax; ++$j) {
      // ...
      if(условие) 
          break 2;
      // ...
   }
   // ...
}

Обработка ошибок

Если в языке нет средств обработки исключений, то оператор goto может использоваться для прерывания «нормального» выполнения кода и перехода к завершающему коду для освобождения занятой памяти и прочих финальных действий. Пример на языке Си:

int fn (int* presult)
{
  int sts = 0;
  TYPE entity, another_entity = NULL;
  TYPE2 entity2 = NULL;

  if ( !( entity = create_entity() ) )
    { sts = ERROR_CODE1; goto exit0; }

  if ( !do_something( entity ) )
    { sts = ERROR_CODE2; goto exit1; }

  if ( condition ) {
    if ( !( entity2 = create_another_entity() ) )
      { sts = ERROR_CODE3; goto exit1; }

    if ( ( *presult = do_another_thing( entity2 ) == NEGATIVE )
      { sts = ERROR_CODE4; goto exit2; }
  } 
  else {
    if ( ( *presult = do_something_special( entity ) == NEGATIVE )
      { sts = ERROR_CODE5; goto exit2; }
  }
  exit2: if ( entity2 ) destroy_another_entity( entity2 );
  exit1: destroy_entity( entity );
  exit0: return sts;
}

Без goto подобный код был бы излишне загромождён множеством дополнительных условных операторов if.

Автогенерация кода

Ещё одним допустимым применением безусловного перехода считается код, который генерируется автоматически, например, генерируемые с помощью программных инструментальных средств лексические и синтаксические анализаторы. Так, код, генерируемый утилитами yacc, lex, bison, изобилует командами goto, но этот код в принципе не предназначен для восприятия и редактирования человеком, а его корректность целиком определяется корректностью создающего его инструмента.

В культуре

В сериале Футурама, в церкви роботов фигурируют афористичные высказывания, оформленные в стиле операторов языка Бейсик:

  • В одной из серий свадьба роботов проходила в церкви роботов, над алтарём которой была написана заповедь:
    10 SIN
    20 GOTO HELL

    (греши, потом иди в ад)
  • В серии «I, Roommate» в квартире Фрая и Бендера на картине есть надпись:
    10 HOME
    20 SWEET
    30 GOTO 10

    (дом, милый [дом, милый…])

Напишите отзыв о статье "Goto"

Примечания

  1. [www.docjar.com/docs/api/com/sun/org/apache/bcel/internal/generic/GOTO.html com.sun.org.apache.bcel.internal.generic: public class: GOTO]
  2. [khpi-iip.mipk.kharkiv.edu/library/extent/dijkstra/pp/ewd215.html Э. Дейкстра. Доводы против оператора goto]
  3. Donald Knuth. [pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf Structured Programming with go to Statements] 1974
  4. [www.stevemcconnell.com/ccgoto.htm Code Complete: A Practical Handbook of Software Construction] Redmond: Microsoft Press, 1993. 880 p.
  5. [www.compiler.su/prodolzhenie-tsikla-i-vykhod-iz-nego.php Продолжение цикла и выход из него]

Ссылки

  • [delphibasics.ru/Goto.php goto в Pascal, Delphi] (рус.)
  • Carl Youngblood. [youngbloods.org/essays/argument_for_goto.html An Argument for the Use of goto Statements] (англ.)

Отрывок, характеризующий Goto

Но доктор перебил его и подвинулся к бричке.
– Я бы вас проводил, да, ей богу, – вот (доктор показал на горло) скачу к корпусному командиру. Ведь у нас как?.. Вы знаете, граф, завтра сражение: на сто тысяч войска малым числом двадцать тысяч раненых считать надо; а у нас ни носилок, ни коек, ни фельдшеров, ни лекарей на шесть тысяч нет. Десять тысяч телег есть, да ведь нужно и другое; как хочешь, так и делай.
Та странная мысль, что из числа тех тысяч людей живых, здоровых, молодых и старых, которые с веселым удивлением смотрели на его шляпу, было, наверное, двадцать тысяч обреченных на раны и смерть (может быть, те самые, которых он видел), – поразила Пьера.
Они, может быть, умрут завтра, зачем они думают о чем нибудь другом, кроме смерти? И ему вдруг по какой то тайной связи мыслей живо представился спуск с Можайской горы, телеги с ранеными, трезвон, косые лучи солнца и песня кавалеристов.
«Кавалеристы идут на сраженье, и встречают раненых, и ни на минуту не задумываются над тем, что их ждет, а идут мимо и подмигивают раненым. А из этих всех двадцать тысяч обречены на смерть, а они удивляются на мою шляпу! Странно!» – думал Пьер, направляясь дальше к Татариновой.
У помещичьего дома, на левой стороне дороги, стояли экипажи, фургоны, толпы денщиков и часовые. Тут стоял светлейший. Но в то время, как приехал Пьер, его не было, и почти никого не было из штабных. Все были на молебствии. Пьер поехал вперед к Горкам.
Въехав на гору и выехав в небольшую улицу деревни, Пьер увидал в первый раз мужиков ополченцев с крестами на шапках и в белых рубашках, которые с громким говором и хохотом, оживленные и потные, что то работали направо от дороги, на огромном кургане, обросшем травою.
Одни из них копали лопатами гору, другие возили по доскам землю в тачках, третьи стояли, ничего не делая.
Два офицера стояли на кургане, распоряжаясь ими. Увидав этих мужиков, очевидно, забавляющихся еще своим новым, военным положением, Пьер опять вспомнил раненых солдат в Можайске, и ему понятно стало то, что хотел выразить солдат, говоривший о том, что всем народом навалиться хотят. Вид этих работающих на поле сражения бородатых мужиков с их странными неуклюжими сапогами, с их потными шеями и кое у кого расстегнутыми косыми воротами рубах, из под которых виднелись загорелые кости ключиц, подействовал на Пьера сильнее всего того, что он видел и слышал до сих пор о торжественности и значительности настоящей минуты.


Пьер вышел из экипажа и мимо работающих ополченцев взошел на тот курган, с которого, как сказал ему доктор, было видно поле сражения.
Было часов одиннадцать утра. Солнце стояло несколько влево и сзади Пьера и ярко освещало сквозь чистый, редкий воздух огромную, амфитеатром по поднимающейся местности открывшуюся перед ним панораму.
Вверх и влево по этому амфитеатру, разрезывая его, вилась большая Смоленская дорога, шедшая через село с белой церковью, лежавшее в пятистах шагах впереди кургана и ниже его (это было Бородино). Дорога переходила под деревней через мост и через спуски и подъемы вилась все выше и выше к видневшемуся верст за шесть селению Валуеву (в нем стоял теперь Наполеон). За Валуевым дорога скрывалась в желтевшем лесу на горизонте. В лесу этом, березовом и еловом, вправо от направления дороги, блестел на солнце дальний крест и колокольня Колоцкого монастыря. По всей этой синей дали, вправо и влево от леса и дороги, в разных местах виднелись дымящиеся костры и неопределенные массы войск наших и неприятельских. Направо, по течению рек Колочи и Москвы, местность была ущелиста и гориста. Между ущельями их вдали виднелись деревни Беззубово, Захарьино. Налево местность была ровнее, были поля с хлебом, и виднелась одна дымящаяся, сожженная деревня – Семеновская.
Все, что видел Пьер направо и налево, было так неопределенно, что ни левая, ни правая сторона поля не удовлетворяла вполне его представлению. Везде было не доле сражения, которое он ожидал видеть, а поля, поляны, войска, леса, дымы костров, деревни, курганы, ручьи; и сколько ни разбирал Пьер, он в этой живой местности не мог найти позиции и не мог даже отличить ваших войск от неприятельских.
«Надо спросить у знающего», – подумал он и обратился к офицеру, с любопытством смотревшему на его невоенную огромную фигуру.
– Позвольте спросить, – обратился Пьер к офицеру, – это какая деревня впереди?
– Бурдино или как? – сказал офицер, с вопросом обращаясь к своему товарищу.
– Бородино, – поправляя, отвечал другой.
Офицер, видимо, довольный случаем поговорить, подвинулся к Пьеру.
– Там наши? – спросил Пьер.
– Да, а вон подальше и французы, – сказал офицер. – Вон они, вон видны.
– Где? где? – спросил Пьер.
– Простым глазом видно. Да вот, вот! – Офицер показал рукой на дымы, видневшиеся влево за рекой, и на лице его показалось то строгое и серьезное выражение, которое Пьер видел на многих лицах, встречавшихся ему.
– Ах, это французы! А там?.. – Пьер показал влево на курган, около которого виднелись войска.
– Это наши.
– Ах, наши! А там?.. – Пьер показал на другой далекий курган с большим деревом, подле деревни, видневшейся в ущелье, у которой тоже дымились костры и чернелось что то.
– Это опять он, – сказал офицер. (Это был Шевардинский редут.) – Вчера было наше, а теперь его.
– Так как же наша позиция?
– Позиция? – сказал офицер с улыбкой удовольствия. – Я это могу рассказать вам ясно, потому что я почти все укрепления наши строил. Вот, видите ли, центр наш в Бородине, вот тут. – Он указал на деревню с белой церковью, бывшей впереди. – Тут переправа через Колочу. Вот тут, видите, где еще в низочке ряды скошенного сена лежат, вот тут и мост. Это наш центр. Правый фланг наш вот где (он указал круто направо, далеко в ущелье), там Москва река, и там мы три редута построили очень сильные. Левый фланг… – и тут офицер остановился. – Видите ли, это трудно вам объяснить… Вчера левый фланг наш был вот там, в Шевардине, вон, видите, где дуб; а теперь мы отнесли назад левое крыло, теперь вон, вон – видите деревню и дым? – это Семеновское, да вот здесь, – он указал на курган Раевского. – Только вряд ли будет тут сраженье. Что он перевел сюда войска, это обман; он, верно, обойдет справа от Москвы. Ну, да где бы ни было, многих завтра не досчитаемся! – сказал офицер.
Старый унтер офицер, подошедший к офицеру во время его рассказа, молча ожидал конца речи своего начальника; но в этом месте он, очевидно, недовольный словами офицера, перебил его.
– За турами ехать надо, – сказал он строго.
Офицер как будто смутился, как будто он понял, что можно думать о том, сколь многих не досчитаются завтра, но не следует говорить об этом.
– Ну да, посылай третью роту опять, – поспешно сказал офицер.
– А вы кто же, не из докторов?
– Нет, я так, – отвечал Пьер. И Пьер пошел под гору опять мимо ополченцев.
– Ах, проклятые! – проговорил следовавший за ним офицер, зажимая нос и пробегая мимо работающих.
– Вон они!.. Несут, идут… Вон они… сейчас войдут… – послышались вдруг голоса, и офицеры, солдаты и ополченцы побежали вперед по дороге.
Из под горы от Бородина поднималось церковное шествие. Впереди всех по пыльной дороге стройно шла пехота с снятыми киверами и ружьями, опущенными книзу. Позади пехоты слышалось церковное пение.
Обгоняя Пьера, без шапок бежали навстречу идущим солдаты и ополченцы.
– Матушку несут! Заступницу!.. Иверскую!..
– Смоленскую матушку, – поправил другой.
Ополченцы – и те, которые были в деревне, и те, которые работали на батарее, – побросав лопаты, побежали навстречу церковному шествию. За батальоном, шедшим по пыльной дороге, шли в ризах священники, один старичок в клобуке с причтом и певчпми. За ними солдаты и офицеры несли большую, с черным ликом в окладе, икону. Это была икона, вывезенная из Смоленска и с того времени возимая за армией. За иконой, кругом ее, впереди ее, со всех сторон шли, бежали и кланялись в землю с обнаженными головами толпы военных.
Взойдя на гору, икона остановилась; державшие на полотенцах икону люди переменились, дьячки зажгли вновь кадила, и начался молебен. Жаркие лучи солнца били отвесно сверху; слабый, свежий ветерок играл волосами открытых голов и лентами, которыми была убрана икона; пение негромко раздавалось под открытым небом. Огромная толпа с открытыми головами офицеров, солдат, ополченцев окружала икону. Позади священника и дьячка, на очищенном месте, стояли чиновные люди. Один плешивый генерал с Георгием на шее стоял прямо за спиной священника и, не крестясь (очевидно, пемец), терпеливо дожидался конца молебна, который он считал нужным выслушать, вероятно, для возбуждения патриотизма русского народа. Другой генерал стоял в воинственной позе и потряхивал рукой перед грудью, оглядываясь вокруг себя. Между этим чиновным кружком Пьер, стоявший в толпе мужиков, узнал некоторых знакомых; но он не смотрел на них: все внимание его было поглощено серьезным выражением лиц в этой толпе солдат и оиолченцев, однообразно жадно смотревших на икону. Как только уставшие дьячки (певшие двадцатый молебен) начинали лениво и привычно петь: «Спаси от бед рабы твоя, богородице», и священник и дьякон подхватывали: «Яко вси по бозе к тебе прибегаем, яко нерушимой стене и предстательству», – на всех лицах вспыхивало опять то же выражение сознания торжественности наступающей минуты, которое он видел под горой в Можайске и урывками на многих и многих лицах, встреченных им в это утро; и чаще опускались головы, встряхивались волоса и слышались вздохи и удары крестов по грудям.
Толпа, окружавшая икону, вдруг раскрылась и надавила Пьера. Кто то, вероятно, очень важное лицо, судя по поспешности, с которой перед ним сторонились, подходил к иконе.
Это был Кутузов, объезжавший позицию. Он, возвращаясь к Татариновой, подошел к молебну. Пьер тотчас же узнал Кутузова по его особенной, отличавшейся от всех фигуре.
В длинном сюртуке на огромном толщиной теле, с сутуловатой спиной, с открытой белой головой и с вытекшим, белым глазом на оплывшем лице, Кутузов вошел своей ныряющей, раскачивающейся походкой в круг и остановился позади священника. Он перекрестился привычным жестом, достал рукой до земли и, тяжело вздохнув, опустил свою седую голову. За Кутузовым был Бенигсен и свита. Несмотря на присутствие главнокомандующего, обратившего на себя внимание всех высших чинов, ополченцы и солдаты, не глядя на него, продолжали молиться.