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

发布于 2024-10-22 20:06:40 字数 75 浏览 5 评论 0原文

| GOTO '*' expr ';'

我还没有见过这样的说法,有人可以举个例子吗?

| GOTO '*' expr ';'

I've never see such statements yet,anyone can bring an example?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

末骤雨初歇 2024-10-29 20:06:40

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


例如,我应用此扩展来给出 回答 在没有循环或条件的情况下打印 1 到 1000< /a> 问题:

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

This is so called Labels as Values and represents one of the GCC extensions.


As an example, I've applied this extension to give an answer to Printing 1 to 1000 without loop or conditionals question:

void printMe () 
{
    int i = 1;
    startPrintMe:
    printf ("%d\n", i);
    void *labelPtr = &&startPrintMe + (&&exitPrintMe - &&startPrintMe) * (i++ / 1000);
    goto *labelPtr;
    exitPrintMe:
}
甜尕妞 2024-10-29 20:06:40

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

IIRC that's a GNU-ism for tail calls. Normally you'd leave that optimization to the compiler, but it can be useful when writing kernels or embedded device drivers.

权谋诡计 2024-10-29 20:06:40

这是海湾合作委员会特有的。它不是标准 C(C89 或 C99)。 (不过,有时它会派上用场,能够进行计算的 goto。)

That is GCC specific. It is not standard C (either C89 or C99). (It would come in handy sometimes though, to be able to do computed gotos.)

酷遇一生 2024-10-29 20:06:40

与已经给出的 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;
}

Similar to PrintMe() already given, here is my solution using a "jump table" solving the same problem except it can do an arbitary # of operations, in this case printf(). Note that the referenced labels must be local to the function.

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;
}
獨角戲 2024-10-29 20:06:40

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

除了上述用途之外,还有绕过返回系统和手动处理函数尾声的用途。

虽然这种情况的用例很少,但它对于编写完全基于 C 的异常 ABI 很有用。我为一个非常传统的平台编写的异常 ABI 使用这些来执行没有缓冲区的长跳转。 (是的,我确实事先恢复了堆栈帧,并且确保跳转是安全的)。

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

一般来说,不应使用该语法。如果需要本地跳转,请使用显式 goto 或实际控制块,如果需要非本地跳转,请使用 longjmp(如有必要),并尽可能使用 C++ 中的异常

Like others have stated, it's a GNU C extension (https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html).

In addition to the above uses, there is a use in Bypassing the return system, and manually handling function(s)'s epiloge.

While the use cases for this are few and far between, it would be useful in writing a fully C-based Exception ABI. The Exception ABI I wrote for a very legacy platform uses these to perform Longjumps without a buffer. (Yes I do reinstate the stack frame before hand, and I make sure that the jump is safe).

Additionally, it could be used for a "JSR" finally block, like in Java prior to java 7, where prior to the return, an explicit return label is stored, and then the finally block is executed. Same prior to any exception being thrown or rethrown (the documentation does not say anything about it not being valid in GNU C++, but I would probably not use it in C++ at all).

In general, the syntax should not be used. If you need local jumps, use explicit gotos or actual control blocks, if you need non-local jumps use longjmp if you have to, and exceptions in C++ where possible

殤城〤 2024-10-29 20:06:40

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

Never. It's not C. It is possible in "GNU C", but it's, as Paul commented, "one of the worst features of FORTRAN", "ported...into C", and thus should be Considered Harmful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文