Is it possible to store the address of a label in

2019-01-21 05:49发布

I know everyone hates gotos. In my code, for reasons I have considered and am comfortable with, they provide an effective solution (ie I'm not looking for "don't do that" as an answer, I understand your reservations, and understand why I am using them anyway).

So far they have been fantastic, but I want to expand the functionality in such a way that requires me to essentially be able to store pointers to the labels, then go to them later.

If this code worked, it would represent the type of functionality that I need. But it doesn't work, and 30 min of googling hasn't revealed anything. Does anyone have any ideas?

int main (void)
{
  int i=1;
  void* the_label_pointer;

  the_label:

  the_label_pointer = &the_label;

  if( i-- )
    goto *the_label_pointer;

  return 0;
}

14条回答
可以哭但决不认输i
2楼-- · 2019-01-21 06:07

I will note that the functionally described here (including && in gcc) is IDEAL for implementing a Forth language interpreter in C. That blows all the "don't do that" arguments out of the water - the fit between that functionality and the way Forth's inner interpreter works is too good to ignore.

查看更多
一夜七次
3楼-- · 2019-01-21 06:07

Read this: setjmp.h - Wikipedia As previously said it is possible with setjmp/longjmp with which you can store a jumppoint in a variable and jump back later.

查看更多
做个烂人
4楼-- · 2019-01-21 06:08

According to the C99 standard, § 6.8.6, the syntax for a goto is:

    goto identifier ;

So, even if you could take the address of a label, you couldn't use it with goto.

You could combine a goto with a switch, which is like a computed goto, for a similar effect:

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

If you use this for anything other than an obfuscated C contest, I will hunt you down and hurt you.

查看更多
SAY GOODBYE
5楼-- · 2019-01-21 06:17

According to this thread, label points are not a standard, so whether they work or not would depend on the compiler you're using.

查看更多
男人必须洒脱
6楼-- · 2019-01-21 06:17

You can do something like Fortran's computer goto with pointers to functions.

// global variables up here

void c1(){ // chunk of code

}

void c2(){ // chunk of code

}

void c3(){ // chunk of code

}

void (*goTo[3])(void) = {c1, c2, c3};

// then
int x = 0;

goTo[x++] ();

goTo[x++] ();

goTo[x++] ();

查看更多
SAY GOODBYE
7楼-- · 2019-01-21 06:18

In the very very very old version of C language (think of the time dinosaurs roamed the Earth), known as "C Reference Manual" version (which refers to a document written by Dennis Ritchie), labels formally had type "array of int" (strange, but true), meaning that you could declare an int * variable

int *target;

and assign the address of label to that variable

target = label; /* where `label` is some label */

Later you could use that variable as the operand of goto statement

goto target; /* jumps to label `label` */

However, in ANSI C this feature was thrown out. In the standard modern C you cannot take address of a label and you cannot do "parametrized" goto. This behavior is supposed to be simulated with switch statements, pointers-to-functions and other methods etc. Actually, even "C Reference Manual" itself said that "Label variables are a bad idea in general; the switch statement makes them almost always unnecessary" (see "14.4 Labels").

查看更多
登录 后发表回答