Поскольку проверка переполнение занимает время. Каждая примитивная математическая операция, которая обычно переводит в единственную инструкцию по сборке, должна была бы включать проверку на переполнение, приводящее к нескольким инструкциям по сборке, потенциально приводящим к программе, которая несколько раз медленнее.
Стандарты C и C ++ не поддерживают эту функцию. Однако коллекция компиляторов GNU (GCC) включает нестандартное расширение для этого, как описано в этой статье . По сути, они добавили специальный оператор «&&», который сообщает адрес метки как тип «void *». Подробнее см. В статье.
PS Другими словами, просто используйте «&&» вместо «&» в вашем примере, и это будет работать в GCC.
PPS Я знаю, что вы не хотите, чтобы я это говорил, но я все равно скажу, ... НЕ ДЕЛАЙТЕ ЭТО !!!
Согласно этого потока , точки меток не являются стандартом, поэтому работают они или нет, будет зависеть от используемого вами компилятора.
Прочтите это: setjmp.h - Википедия Как было сказано ранее, это возможно с setjmp / longjmp, с помощью которого вы можете сохранить точку перехода в переменной и вернуться к ней позже.
Используйте указатели на функции и цикл while. Не создавайте фрагмент кода, кому-то другому придется пожалеть об исправлении за вас.
Я предполагаю, что вы пытаетесь каким-то образом изменить адрес метки извне. Указатели функций будут работать.
В очень-очень старой версии языка C (вспомните время, когда динозавры бродили по Земле), известной как версия «Справочного руководства C» (которая относится к документу ] написано Деннисом Ричи), метки формально имели тип «массив int» (странно, но верно), что означало, что вы могли объявить переменную int *
int *target;
и присвоить этой переменной адрес метки.
target = label; /* where `label` is some label */
Позже вы могли использовать эту переменную в качестве операнда оператора goto
goto target; /* jumps to label `label` */
Однако в ANSI C эта функция была исключена. В стандартном современном C вы не можете брать адрес метки и не можете делать "параметризованный" goto
. Предполагается, что такое поведение моделируется с помощью операторов switch
, указателей на функции и других методов и т. Д. На самом деле, даже " В самом справочном руководстве C говорилось, что «метки переменных - плохая идея; оператор switch делает их почти всегда ненужными »(см. « 14.4 Метки »).
Согласно стандарту C99, § 6.8.6, синтаксис для goto
таков:
goto identifier ;
Итак, даже если вы могли бы взять адрес метки, вы не могли использовать его с goto.
Вы можете объединить goto
с переключателем
, который похож на вычисляемый goto
, для аналогичного эффекта :
int foo() {
static int i=0;
return i++;
}
int main(void) {
enum {
skip=-1,
run,
jump,
scamper
} label = skip;
#define STATE(lbl) case lbl: puts(#lbl); break
computeGoto:
switch (label) {
case skip: break;
STATE(run);
STATE(jump);
STATE(scamper);
default:
printf("Unknown state: %d\n", label);
exit(0);
}
#undef STATE
label = foo();
goto computeGoto;
}
Если вы будете использовать это для чего-нибудь, кроме замаскированного конкурса C, я выслежу вас и причиню вам боль.
Оператор switch ... case
по сути является вычисленным goto
. Хорошим примером того, как это работает, является странный хак, известный как Устройство Даффа :
send(to, from, count)
register short *to, *from;
register count;
{
register n=(count+7)/8;
switch(count%8){
case 0: do{ *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
}while(--n>0);
}
}
Вы не можете выполнить goto
из произвольного места, используя эту технику, но вы можете обернуть всю вашу функцию в операторе switch
на основе переменной, затем установите эту переменную, указывающую, куда вы хотите перейти, и goto
этот оператор переключения.
int main () {
int label = 0;
dispatch: switch (label) {
case 0:
label = some_computation();
goto dispatch;
case 1:
label = another_computation();
goto dispatch;
case 2:
return 0;
}
}
Конечно, если вы это сделаете это много, вам нужно написать несколько макросов, чтобы обернуть это.
Этот метод, вместе с некоторыми вспомогательными макросами, можно даже использовать для реализации сопрограмм в C .
Вы можете сделать нечто подобное с помощью setjmp / longjmp.
int main (void)
{
jmp_buf buf;
int i=1;
// this acts sort of like a dynamic label
setjmp(buf);
if( i-- )
// and this effectively does a goto to the dynamic label
longjmp(buf, 1);
return 0;
}
Единственная официально поддерживаемая вещь, которую вы можете делать с меткой в C, - это goto
it. Как вы заметили, вы не можете взять его адрес, сохранить его в переменной или что-то еще. Поэтому вместо того, чтобы сказать «не делайте этого», я скажу «вы не можете этого сделать».
Похоже, вам придется найти другое решение. Может быть, язык ассемблера, если это критично для производительности?