6.12.2 Локально объявленные метки
GCC позволяет объявлять локальные метки в любой вложенной области видимости блока. Локальная метка аналогична обычной метке, но ссылаться на неё (с помощью оператора goto или получая её адрес) можно только в блоке, в котором она объявлена.
Объявление локальной метки выглядит так:
__label__ label;
или так:
__label__ label1, label2, /* … */;
Объявления локальных меток должны располагаться в начале блока, перед любыми обычными объявлениями или операторами.
Объявление метки определяет имя метки, но не определяет саму метку. Это нужно сделать обычным способом, с помощью 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-15.3.0/gcc/Local-Labels.html