可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I want to declare an array of "jumplabels".
Then I want to jump to a "jumplabel" in this array.
But I have not any idea how to do this.
It should look like the following code:
function()
{
"gotolabel" s[3];
s[0] = s0;
s[1] = s1;
s[2] = s2;
s0:
....
goto s[v];
s1:
....
goto s[v];
s2:
....
goto s[v];
}
Does anyone have a idea how to perform this?
回答1:
It is possible with GCC feature known as "labels as values".
void *s[3] = {&&s0, &&s1, &&s2};
if (n >= 0 && n <=2)
goto *s[n];
s0:
...
s1:
...
s2:
...
It works only with GCC!
回答2:
goto
needs a compile-time label.
From this example it seems that you are implementing some kind of state machine. Most commonly they are implemented as a switch-case construct:
while (!finished) switch (state) {
case s0:
/* ... */
state = newstate;
break;
/* ... */
}
If you need it to be more dynamic, use an array of function pointers.
回答3:
There's no direct way to store code addresses to jump to in C.
How about using switch.
#define jump(x) do{ label=x; goto jump_target; }while(0)
int label=START;
jump_target:
switch(label)
{
case START:
/* ... */
case LABEL_A:
/* ... */
}
You can find similar code produced by every stack-less parser / state machine generator.
Such code is not easy to follow so unless it is generated code or your problem is most
easily described by state machine I would recommend not do this.
回答4:
could you use function pointers instead of goto?
That way you can create an array of functions to call and call the appropriate one.
回答5:
In plain standard C, this not possible as far as I know. There is however an extension in the GCC compiler, documented here, that makes this possible.
The extension introduces the new operator &&
, to take the address of a label, which can then be used with the goto
statement.
回答6:
That's what switch
statements are for.
switch (var)
{
case 0:
/* ... */
break;
case 1:
/* ... */
break;
default:
/* ... */
break; /* not necessary here */
}
Note that it's not necessarily translated into a jump table by the compiler.
If you really want to build the jump table yourself, you could use a function pointers array.
回答7:
You might want to look at setjmp/longjmp.
回答8:
You can't do it with a goto - the labels have to be identifiers, not variables or constants. I can't see why you would not want to use a switch here - it will likely be just as efficient, if that is what is concerning you.
回答9:
For a simple answer, instead of forcing compilers to do real stupid stuff, learn good programming practices.
回答10:
Tokenizer? This looks like what gperf was made for. No really, take a look at it.
回答11:
Optimizing compilers (including GCC) will compile a switch statement into a jump table (making a switch statement exactly as fast as the thing you're trying to construct) IF the following conditions are met:
Your switch cases (state numbers) start at zero.
Your switch cases are strictly increasing.
You don't skip any integers in your switch cases.
There are enough cases that a jump table is actually faster (a couple dozen compare-and-gotos in the checking-each-case method of dealing with switch statements is actually faster than a jump table.)
This has the advantage of allowing you to write your code in standard C instead of relying on a compiler extension. It will work just as fast in GCC. It will also work just as fast in most optimizing compilers (I know the Intel compiler does it; not sure about Microsoft stuff). And it will work, although slower, on any compiler.