Меню

Метки инструкций имеют область видимости

Урок №66. Оператор goto

Обновл. 1 Авг 2020 |

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

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

Ранее мы рассматривали два типа области видимости: локальная (или «блочная») и глобальная (или «файловая»). Лейблы используют третий тип области видимости: область видимости функции. Оператор goto и соответствующий лейбл должны находиться в одной и той же функции.

Существуют некоторые ограничения на использование операторов goto. Например, вы не сможете перепрыгнуть вперед через переменную, которая инициализирована в том же блоке, что и goto:

В целом, программисты избегают использования оператора goto в языке C++ (и в большинстве других высокоуровневых языков программирования). Основная проблема с ним заключается в том, что он позволяет программисту управлять выполнением кода так, что точка выполнения может прыгать по коду произвольно. А это, в свою очередь, создает то, что опытные программисты называют «спагетти-кодом». Спагетти-код — это код, порядок выполнения которого напоминает тарелку со спагетти (всё запутано и закручено), что крайне затрудняет следование порядку и понимание логики выполнения такого кода.

Как говорил один известный специалист в информатике и программировании, Эдсгер Дейкстра: «Качество программистов — это уменьшающаяся функция плотности использования операторов goto в программах, которые они пишут».

Оператор goto часто используется в некоторых старых языках, таких как Basic или Fortran, или даже в языке Cи. Однако в C++ goto почти никогда не используется, поскольку любой код, написанный с ним, можно более эффективно переписать с использованием других объектов в языке C++, таких как циклы, обработчики исключений или деструкторы (всё перечисленное мы рассмотрим чуть позже).

Правило: Избегайте использования операторов goto, если на это нет веских причин.

Источник



Инструкция goto и метки

В Си имеется порицаемая многими инструкция goto и метки для перехода на них. Строго говоря, в этой инструкции нет никакой необходимости, и на практике почти всегда легко без нее обойтись. До сих пор в нашей книге мы не использовали goto .

Однако существуют случаи, в которых goto может пригодиться. Наиболее типична ситуация, когда нужно прервать обработку в некоторой глубоко вложенной структуре и выйти сразу из двух или большего числа вложенных циклов. Инструкция break здесь не поможет, так как она обеспечит выход только из самого внутреннего цикла. В качестве примера рассмотрим следующую конструкцию:

Читайте также:  Купите переносной галогенный аккумуляторный фонарь ФОС 3 5 6 с поворотной фарой по оптовой цене в Санкт Петербурге Москве России

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

Метка выглядит как обычное имя переменной, за которым следует двоеточие. На метку можно перейти с помощью goto из любого места данной функции, т.е. метка видима для всей функции.

В качестве еще одного примера рассмотрим такую задачу: определить, есть ли в массивах a и b совпадающие элементы. Один из возможных вариантов ее реализации имеет следующий вид:

Программу нахождения совпадающих элементов можно написать и без goto , правда, заплатив за это дополнительными проверками и еще одной переменной:

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

Источник

7.6 – Операторы goto

Следующий тип инструкций управления порядком выполнения программы, который мы рассмотрим, – это безусловный переход. Безусловный переход заставляет выполнение перемещаться в другое место в коде. Термин «безусловный» означает, что переход происходит всегда (в отличие от оператора if или оператора switch , где переход происходит только на основе результата условного выражения).

В C++ безусловные переходы реализуются с помощью инструкции goto , а точка перехода определяется с помощью метки инструкции. Ниже приведен пример инструкции goto и метки инструкции:

В этой программе пользователя просят ввести неотрицательное число. Однако если введено отрицательное число, программа использует инструкцию goto для возврата к метке tryAgain . Затем пользователя снова просят ввести новое число. Таким образом, мы можем постоянно просить пользователя ввести данные, пока он или она не введет что-то допустимое.

Вот пример вывода при запуске этой программы:

Метки инструкций имеют область видимости

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

Хотя в приведенном выше примере показана инструкция goto , которая выполняет переход назад (к предыдущей точке в функции), инструкции goto могут перемещаться и вперед:

Эта программа напечатает:

Помимо перехода вперед, в приведенной выше программе стоит упомянуть еще несколько интересных вещей.

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

Читайте также:  Водяной тепловентилятор Sonniger HEATER ONE

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

Обратите внимание, что вы можете выполнить переход назад через инициализацию переменной, и при выполнении инициализации переменная будет повторно инициализирована.

Избегайте использования goto

Использование goto в C++ (а также в других современных высокоуровневых языках) не допускается. Эдсгер В. Дейкстра, известный ученый-информатик, изложил аргументы в пользу отказа от goto в известной, но трудной для чтения статье под названием «Go To Statement Considered Harmful». Основная проблема с goto заключается в том, что он позволяет программисту произвольно перемещаться по коду. Это создает то, что не очень ласково называют спагетти-кодом. Спагетти-код – это код, порядок выполнения которого напоминает тарелку спагетти (все запутанные и скрученные), что чрезвычайно затрудняет отслеживание логики такого кода.

Как с юмором говорит Дейкстра, «качество программистов – это функция, обратно пропорциональная плотности инструкций переходов в создаваемых ими программах».

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

Лучшая практика

Избегайте операторов goto (если альтернативы значительно не ухудшают читаемость кода).

Источник

Инструкция goto и метки

Оглавление книги Популярные страницы Скачать книгу Купить книгу

Книга широко известных авторов, разработчиков языка Си, переработанная и дополненная с учетом стандарта ANSI для языка Си, 2-е английское издание которой вышло в 1988 году, давно стала классикой для всех изучающих и/или использующих как Си, так и Си++. Русский перевод этой книги впервые был выпущен изд- вом «Финансы и статистика» в 1992 г. и с тех пор пользуется неизменным спросом читателей.

Читайте также:  Dsd4514r с дизайнерским шариком в виде логотипа нтв плюс

Для настоящего третьего русского издания перевод заново сверен с оригиналом, в него внесены некоторые поправки, учитывающие устоявшиеся за прошедшие годы изменения в терминологии, а так же учтены замечания, размещенные автором на странице http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html.

Для программистов, преподавателей и студентов.

Издание подготовлено при участии издательства «Финансы и статистика»

Книга: Язык программирования Си. Издание 3-е, исправленное

3.8 Инструкция goto и метки

3.8 Инструкция goto и метки

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

Однако существуют случаи, в которых goto может пригодиться. Наиболее типична ситуация, когда нужно прервать обработку в некоторой глубоко вложенной структуре и выйти сразу из двух или большего числа вложенных циклов. Инструкция break здесь не поможет, так как она обеспечит выход только из самого внутреннего цикла. В качестве примера рассмотрим следующую конструкцию:

for (…)
for (…) <

if (disaster) /* если бедствие */
goto error; /* уйти на ошибку */
error: /* обработка ошибки */
ликвидировать беспорядок

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

Метка имеет вид обычного имени переменной, за которым следует двоеточие. На метку можно перейти с помощью goto из любого места данной функции, т. е. метка видима на протяжении всей функции.

В качестве еще одного примера рассмотрим такую задачу: определить, есть ли в массивах a и b совпадающие элементы. Один из возможных вариантов ее реализации имеет следующий вид:

for (i = 0; i ‹ n; i++)
for (j = 0; j ‹ m; j++)
if (a[i] == b[i])
goto found;
/* нет одинаковых элементов */

found:
/* обнаружено совпадение: a[i] — b[i] */

Программу нахождения совпадающих элементов можно написать и без goto, правда, заплатив за это дополнительными проверками и еще одной переменной:

found = 0;
for (i = 0; i ‹ n && !found; i++)
for (j = 0; j ‹ m && !found; j++)
if (a[i] == b[j])
found = 1;
if (found) /* обнаружено совпадение: a[i-1] — b[j-1] */

else
/* нет одинаковых элементов */

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

Источник

Adblock
detector