Вам необходимо расширение __label__
(по крайней мере, в g cc, clang и small cc), которое позволяет размещать метки в блоке.
Метки должны быть объявлены в самом начале блока с
__label__ I0, R0, S0, F0, G0, H0;
(Смежный __label__ I0; __label__ R0; ...
или сочетание двух форм также работает.).
Если не объявлен локальный объем с __label__
, C метки охватываются функцией включения.
Ваш пример с __label__
:
#include "stdio.h"
#define GOTO(X) static void* const caseArg[] = {&&I0, &&R0, &&S0, &&F0, &&G0, &&H0}; \
goto *caseArg[X];
#define FINISH() goto caseEnd;
#define DECL_LBLS() __label__ I0, R0, S0, F0, G0, H0, caseEnd
int main(int argc, char** argv) {
{ DECL_LBLS();
GOTO(2);
I0: printf("in I0\n"); FINISH();
R0: printf("in R0\n"); FINISH();
S0: printf("in S0\n"); FINISH();
F0: printf("in F0\n"); FINISH();
G0: printf("in G0\n"); FINISH();
H0: printf("in H0\n"); FINISH();
caseEnd:;
}
{ DECL_LBLS();
GOTO(1);
I0: printf("in I0\n"); FINISH();
R0: printf("in R0\n"); FINISH();
S0: printf("in S0\n"); FINISH();
F0: printf("in F0\n"); FINISH();
G0: printf("in G0\n"); FINISH();
H0: printf("in H0\n"); FINISH();
caseEnd:;
}
}
https://gcc.godbolt.org/z/63YSkG
In В данном конкретном случае такая перемычка на основе локальной метки, кажется, стоит немного дороже старой switch
.