开发者

When do we use goto *expr; in C?

| GOTO '*' expr ';'

I've never see such stat开发者_JS百科ements yet,anyone can bring an example?


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:
}


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.


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.)


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;
}


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜