Самый базовый и низкоуровневый оператор управления программой - оператор безусловного перехода goto
позволяет перейти к другой строке программы по метке. goto
по сути работает на уровне процессора - переход к другой инструкции в памяти.
Почти все остальные операторы управления программой основаны на механизме goto
и просто обёрнуты в более удобный синтаксис
Для работы оператора нужно создать в программе метку - уникальное имя, после которого стоит двоеточие - имя:
. После этого можно будет перейти к ней при помощи goto имя;
:
goto label;
// код1
// код1
label:
// код2
В данном случае весь "код1" будет пропущен - после строки goto label;
программа перейдет сразу к "код2".
Зацикливание #
Если метка будет объявлена выше, чем goto
:
label:
// код
goto label;
То программа зациклится и будет по кругу выполнять "код", находящийся между label:
и goto label;
.
По условию #
goto
можно выполнять по условию, чтобы создать ветвление программы:
if (a > b) goto label;
// ...
label:
Проблемы #
В общем случае не рекомендуется использовать goto
в своей программе, он плохо читается и может создать путаницу. Доказано, что в любой ситуации можно заменить goto
на другую конструкцию. Также он может приводить к ошибкам, например:
goto label;
int a = 0;
label:
int b = a;
Здесь мы переходим к использованию переменной, которая по сути не была создана и инициализирована - ошибка "передача управления в обход инициализации".
Где использовать #
В то же время в некоторых моментах переход goto
отлично смотрится и позволяет писать удобный и лаконичный код.
Обработка ошибок на нескольких этапах: последовательно проверяем некоторые условия, при возникновении ошибки пропускаем все следующие проверки и переходим к некоторому завершающему коду. Если ошибок нет - выполняется также другой код. Например запрос к серверу с обработкой ошибок подключения, затем разбор результата и так далее.
if (ошибка1) goto exit;
if (ошибка2) goto exit;
if (ошибка3) {
// код3
goto exit;
}
// код, если ошибок нет
exit:
// завершающий код
На if-else
получится примерно такая макаронина, её размер будет увеличиваться при увеличении количества обрабатываемых ошибок:
if (!ошибка1) {
if (!ошибка2) {
if (!ошибка3) {
// код, если ошибок нет
} else {
// код3
}
}
}
// завершающий код
Аналогично - выход из вложенных циклов (о них - в следующем уроке):
for (..) {
for (..) {
for (..) {
if (..) goto exit;
}
}
}
exit:
Здесь без goto
пришлось бы городить флаг, по которому выходить из каждого цикла через break
.