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-11.4.0/gcc/Local-Labels.html