| GOTO '*' expr ';'
我还没有看到过这样的陈述,任何人都可以举一个例子吗?
答案 0 :(得分:6)
这就是所谓的 Labels as Values ,代表GCC扩展之一。
例如,我已应用此扩展程序提出answer至Printing 1 to 1000 without loop or conditionals个问题:
void printMe ()
{
int i = 1;
startPrintMe:
printf ("%d\n", i);
void *labelPtr = &&startPrintMe + (&&exitPrintMe - &&startPrintMe) * (i++ / 1000);
goto *labelPtr;
exitPrintMe:
}
答案 1 :(得分:3)
IIRC这是一个用于尾部调用的GNU-ism。通常,您会将该优化保留给编译器,但在编写内核或嵌入式设备驱动程序时它非常有用。
答案 2 :(得分:2)
这是GCC的具体内容。它不是标准C(C89或C99)。 (虽然有时候它会派上用场,但能够计算得到的。)
答案 3 :(得分:1)
与已经给出的PrintMe()类似,这里是我的解决方案,使用“跳转表”来解决相同的问题,除了它可以执行任意操作,在这种情况下是printf()。请注意,引用的标签必须是函数的本地标签。
int print_iterate( int count )
{
int i=0;
void * jump_table[2] = { &&start_label , &&stop_label };
start_label:
printf( ++i );
// using integer division: i/count will be 0 until count is reached (then it is 1)
goto *jump_table[ i/count ];
stop_label:
return 0;
}
答案 4 :(得分:0)
从不。它不是C.它可能在“GNU C”中,但正如Paul所评论的那样,“FORTRAN最糟糕的特征之一”,“移植到C中”,因此应该被认为是有害的。
答案 5 :(得分:0)
就像其他人所说的那样,它是GNU C扩展(https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html)。
除上述用途外,还有在绕过返回系统和手动处理函数的结语中的用途。
尽管用例很少,但在编写完全基于C的Exception ABI时将很有用。我为非常传统的平台编写的Exception ABI使用它们来执行Longjumps而没有缓冲区。 (是的,我确实事先恢复了堆栈框架,并且确保跳转是安全的)。
此外,它可以用于“ JSR” finally块,就像在Java 7之前的Java中一样,在Java 7中,在返回之前存储一个显式的返回标签,然后执行finally块。在抛出或重新抛出任何异常之前都一样(文档没有说明它在GNU C ++中无效,但是我可能根本不会在C ++中使用它)。
通常,不应使用语法。如果需要本地跳转,请使用显式的gotos或实际的控制块,如果需要非本地跳转,请使用longjmp,并在可能的情况下使用C ++中的异常