6.2 Локально объявленные метки ¶
GCC позволяет объявлять локальные метки в любом блоке кода. Локальная метка — это обычная метка, но вы можете ссылаться на нее (с помощью goto оператора или путем получения ее адреса) только внутри блока, в котором она объявлена.
Объявление локальной метки выглядит следующим образом:
__label__ label;
или
__label__ label1, label2, /* … */;
Объявления локальных меток должны располагаться в начале блока, перед любыми обычными объявлениями или операторами.
Объявление метки определяет имя метки name, но не саму метку. Вы должны сделать это обычным способом, с label:, внутри операторных выражений.
Функциональность локальных меток полезна для сложных макросов. Если макрос содержит вложенные циклы, локальная метка goto может быть полезной для выхода из них. Однако обычная метка, область действия которой — вся функция, использовать нельзя: если макрос может быть расширен несколько раз в одной функции, метка будет многократно определена в этой функции. Локальная метка позволяет избежать этой проблемы. Например:
#define SEARCH(value, array, target) \
do { \
__label__ found; \
typeof (target) _SEARCH_target = (target); \
typeof (*(array)) *_SEARCH_array = (array); \
int i, j; \
int value; \
for (i = 0; i < max; i++) \
for (j = 0; j < max; j++) \
if (_SEARCH_array[i][j] == _SEARCH_target) \
{ (value) = i; goto found; } \
(value) = -1; \
found:; \
} while (0)
Это также можно записать, используя операторное выражение:
#define SEARCH(array, target) \
({ \
__label__ found; \
typeof (target) _SEARCH_target = (target); \
typeof (*(array)) *_SEARCH_array = (array); \
int i, j; \
int value; \
for (i = 0; i < max; i++) \
for (j = 0; j < max; j++) \
if (_SEARCH_array[i][j] == _SEARCH_target) \
{ value = i; goto found; } \
value = -1; \
found: \
value; \
})
Объявления локальных меток также делают объявленные метки видимыми для вложенных функций, если они есть. Подробнее см. Вложенные функции.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-10.5.0/gcc/Local-Labels.html