Инструкция goto
Передаёт управление безусловно в желаемую точку.
Используется, когда иначе невозможно передать управление в желаемую точку с использованием обычных конструкций.
Синтаксис
посл-спец-атр(необязательно) goto метка ;
|
|||||||||
| метка | — | целевая метка для инструкции goto
|
| посл-спец-атр | — | (C23)необязательный список атрибутов, применяемых к инструкции goto
|
Объяснение
Инструкция goto вызывает безусловный переход (передачу управления) на инструкцию, помеченную меткой (которая обязана присутствовать в той же функции, что и инструкция goto), за исключением случая перехода в область видимости массива переменной длины или иного переменно-модифицируемого типа. (начиная с C99)
метка это идентификатор с последующим двоеточием (:) и инструкцией (до C23). Метки это единственные идентификаторы с функциональной областью видимости: они могут использоваться (в инструкции goto) в любом месте одной и той же функции, в которой они появляются. Перед любой инструкцией может быть несколько меток.
|
Переход в область видимости не переменно-модифицируемого типа разрешён: goto lab1; // нормально: переходим в область видимости обычной переменной
int n = 5;
lab1:; // Обратите внимание, n неинициализирована, будто бы объявлена как int n;
// goto lab2; // Ошибка: переходим в область видимости двух ПМ типов
double a[n]; // массив переменной длины
int (*p)[n]; // указатель на массив переменной длины
lab2:
Если {
int n = 1;
label:;
int a[n]; // перевыделяется 10 раз, каждый раз с разным размером
if (n++ < 10) goto label; // покидаем область видимости ПМ
}
|
(начиная с C99) |
Ключевые слова
Замечания
|
Так как объявления это не инструкции, то метка перед объявлением должна быть пустой инструкцией (точка с запятой сразу после двоеточия). То же самое справедливо для метки перед концом блока. |
(до C23) |
C++ накладывает дополнительные ограничения на инструкцию goto, но разрешает метки перед объявлениями (которые являются инструкциями в C++).
Пример
#include <stdio.h>
int main(void)
{
// goto может с лёгкостью выйти из многоуровневых циклов
for (int x = 0; x < 3; x++) {
for (int y = 0; y < 3; y++) {
printf("(%d;%d)\n",x,y);
if (x + y >= 3) goto endloop;
}
}
endloop:;
}
Вывод:
(0;0)
(0;1)
(0;2)
(1;0)
(1;1)
(1;2)
Ссылки
- Стандарт C17 (ISO/IEC 9899:2018):
- 6.8.6.1 Инструкция goto (стр. 110-111)
- Стандарт C11 (ISO/IEC 9899:2011):
- 6.8.6.1 Инструкция goto (стр. 152-153)
- Стандарт C99 (ISO/IEC 9899:1999):
- 6.8.6.1 Инструкция goto (стр. 137-138)
- Стандарт C89/C90 (ISO/IEC 9899:1990):
- 3.6.6.1 Инструкция goto
См. также
Документация C++ по инструкции
goto |