goto

goto

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

Содержание

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

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

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

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

Оператор goto имеется в таких языках, как Фортран, Алгол, Кобол, Бейсик, Си и C++, C#, D, Паскаль, Perl, Ада, PHP и многих других. Он присутствует также во всех языках ассемблера (обычно под названием jmp, jump). Свобода использования 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");
}

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

Если в языке нет средств обработки исключений, то оператор 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

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

Примечания

Ссылки


Wikimedia Foundation. 2010.

Игры ⚽ Нужна курсовая?

Полезное


Смотреть что такое "goto" в других словарях:

  • GOTO — o GO TO (ir a en inglés) es una instrucción muy común en los lenguajes de programación con el objetivo de controlar el flujo del programa. El efecto de su versión más simple es transferir sin condiciones la ejecución del programa a la etiqueta o… …   Wikipedia Español

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

  • Goto — is a statement found in many computer programming languages. It is a combination of the English words and . When executed it causes an unconditional transfer of control (a jump ) to another statement. The jumped to statement is specified using… …   Wikipedia

  • GOTO — L instruction goto (de l anglais go to, en français aller à) est une instruction présente dans de nombreux langages de programmation. Elle est utilisée pour réaliser des sauts inconditionnels dans un programme. L exécution est renvoyée vers une… …   Wikipédia en Français

  • Gotō — Goto steht für: Sprunganweisung, einen Sprung in der Programmierung Goto (Teleskop), eine Vorrichtung an Teleskopen Verein der Künste Hauptsitz in Österreich Gotō (五島) steht außerdem für: Gotō Inseln, eine Inselgruppe in der japanischen Präfektur …   Deutsch Wikipedia

  • Goto — steht für: Sprunganweisung, einen Sprung in der Programmierung Goto (Teleskop), eine Vorrichtung an Teleskopen Gotō (五島) steht außerdem für: Gotō Inseln, eine Inselgruppe in der japanischen Präfektur Nagasaki Gotō (Nagasaki), eine Stadt auf… …   Deutsch Wikipedia

  • Gotō — shi (五島市) Plage d Omaha à Gotō Administration Pays Japon Région Kyūshū Préfecture …   Wikipédia en Français

  • Goto — puede referirse a: GOTO (ir a), instrucción de varios lenguajes de programación; Gotō, apellido japonés; Islas Gotō, archipiélago japonés. Esta página de desambiguación cataloga artículos relacionados con el mismo título. Si llegaste aquí a… …   Wikipedia Español

  • GOTO — o GO TO (ir a en inglés) es una sentencia o instrucción muy común en los lenguajes de programación con el objetivo de controlar el flujo del programa. El efecto de su versión más simple es transferir sin condiciones la ejecución del programa a la …   Enciclopedia Universal

  • goto — |ô| s. m. 1.  [Informal] Glote. 2. O que causa sufocação. 3. dar no goto: entrar na glote (a comida ou a bebida). 4.  [Figurado] Causar estranheza; agradar. • Plural: gotos |ô| …   Dicionário da Língua Portuguesa


Поделиться ссылкой на выделенное

Прямая ссылка:
Нажмите правой клавишей мыши и выберите «Копировать ссылку»