繁体   English   中英

我们什么时候使用goto * expr; 在C?

When do we use goto *expr; in C?

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

| GOTO '*' expr ';'

我还没有看到过这样的陈述,任何人都可以举个例子吗?

6 个回复

这就是所谓的标签作为值 ,代表了GCC扩展之一。


作为一个例子,我已应用此扩展来给出没有循环或条件问题的打印1到1000答案

void printMe () 
{
    int i = 1;
    startPrintMe:
    printf ("%d\n", i);
    void *labelPtr = &&startPrintMe + (&&exitPrintMe - &&startPrintMe) * (i++ / 1000);
    goto *labelPtr;
    exitPrintMe:
}

IIRC是尾部调用的GNU主义。 通常,您会将该优化留给编译器,但在编写内核或嵌入式设备驱动程序时它非常有用。

这是GCC的具体内容。 它不是标准C(C89或C99)。 (虽然它有时会派上用场,但是能够做计算得到的。)

类似于已经给出的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;
}

像其他人所说,它是GNU C扩展( https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html )。

除了上述用途之外,还有一种用途可以绕过返回系统,并手动处理函数的结果。

虽然用于此的用例很少,但在编写完全基于C的异常ABI时会很有用。 我为一个非常遗留的平台编写的异常ABI使用这些来执行没有缓冲区的Longjump。 (是的,我事先恢复了堆栈框架,我确保跳转是安全的)。

另外,它可以用于“JSR”finally块,就像在Java 7之前的Java中一样,在返回之前,存储显式返回标签​​,然后执行finally块。 在抛出或重新抛出任何异常之前相同(文档没有说明它在GNU C ++中无效,但我可能根本不会在C ++中使用它)。

通常,不应使用语法。 如果你需要本地跳转,使用显式的getos或实际的控制块,如果你需要非局部跳转,你可以使用longjmp,并且尽可能使用C ++中的异常

决不。 它不是C.它可能在“GNU C”中,但正如Paul所评论的那样,“FORTRAN最糟糕的特征之一”,“移植到C中”,因此应该被认为是有害的。

5 是否在C#中正确使用了GOTO

我正在跟踪一些代码,并将列表发送到下面,以从列表中删除某些项。 这是使用goto的正确方法吗? 甚至有必要吗? 您是否只将第二个if修改为else if,然后继续处理列表而不需要goto? (这是我第一次在BASIC之外见过goto。) ...

2012-11-29 20:16:18 5 305   c#/ goto
8 从MIPS调用C时,我们使用JR还是JALR?

我正在编写一些自我修改的代码,并且想从MIPS调用C函数(称为foo )。 我已经将foo &foo的内存添加到$t1 。 现在我jr/jalr $t1 。 C是否将$ra设置为我的当前PC(+8)(在跳转之前),允许我使用JR还是我不得不改为JALR (即,照顾它,因为C ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2021 STACKOOM.COM