I want to declare an array of "jumplabels".
我想声明一个“jumplabels”数组。
Then I want to jump to a "jumplabel" in this array.
然后我想跳到这个数组中的“jumplabel”。
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?
有人知道怎么做吗?
11 个解决方案
#1
40
It is possible with GCC feature known as "labels as values".
GCC以“标签为值”的特性是可能的。
void *s[3] = {&&s0, &&s1, &&s2};
if (n >= 0 && n <=2)
goto *s[n];
s0:
...
s1:
...
s2:
...
It works only with GCC!
它只适用于GCC!
#2
17
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
12
There's no direct way to store code addresses to jump to in C. How about using switch.
在c中没有直接存储代码地址的方法,那么使用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
8
could you use function pointers instead of goto?
你能不能用函数指针代替goto?
That way you can create an array of functions to call and call the appropriate one.
这样,您就可以创建一系列函数来调用和调用适当的函数。
#5
6
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.
在普通的标准C中,据我所知这是不可能的。然而,在GCC编译器中有一个扩展,这使得这成为可能。
The extension introduces the new operator &&
, to take the address of a label, which can then be used with the goto
statement.
扩展引入新的运算符&&,以获取标签的地址,然后可以与goto语句一起使用。
#6
5
That's what switch
statements are for.
这就是switch语句的作用。
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
3
You might want to look at setjmp/longjmp.
您可能需要查看setjmp/longjmp。
#8
2
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.
你不能用goto -标签必须是标识符,而不是变量或常量。我不明白你为什么不愿意在这里使用开关——如果这是你所关心的,它很可能同样有效。
#9
1
For a simple answer, instead of forcing compilers to do real stupid stuff, learn good programming practices.
对于一个简单的答案,不要强迫编译器做真正的愚蠢的事情,学习好的编程实践。
#10
1
Tokenizer? This looks like what gperf was made for. No really, take a look at it.
记号赋予器吗?这看起来像gperf的作用。不,看看。
#11
1
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:
如果满足以下条件,优化编译器(包括GCC)将把一个switch语句编译成一个跳转表(使一个switch语句与您试图构建的东西一样快):
Your switch cases (state numbers) start at zero.
你的开关情况(状态数)从0开始。
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.)
有足够多的情况表明跳转表实际上更快(在处理switch语句的检查-case方法中,几十个比较-goto实际上比跳转表快)。
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.
这样做的好处是可以在标准C中编写代码,而不是依赖于编译器扩展。在GCC中,它的工作速度也一样快。在大多数优化编译器中,它的工作速度也一样快(我知道Intel编译器会这么做;不确定微软的东西)。它可以在任何编译器上工作,尽管速度较慢。
#1
40
It is possible with GCC feature known as "labels as values".
GCC以“标签为值”的特性是可能的。
void *s[3] = {&&s0, &&s1, &&s2};
if (n >= 0 && n <=2)
goto *s[n];
s0:
...
s1:
...
s2:
...
It works only with GCC!
它只适用于GCC!
#2
17
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
12
There's no direct way to store code addresses to jump to in C. How about using switch.
在c中没有直接存储代码地址的方法,那么使用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
8
could you use function pointers instead of goto?
你能不能用函数指针代替goto?
That way you can create an array of functions to call and call the appropriate one.
这样,您就可以创建一系列函数来调用和调用适当的函数。
#5
6
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.
在普通的标准C中,据我所知这是不可能的。然而,在GCC编译器中有一个扩展,这使得这成为可能。
The extension introduces the new operator &&
, to take the address of a label, which can then be used with the goto
statement.
扩展引入新的运算符&&,以获取标签的地址,然后可以与goto语句一起使用。
#6
5
That's what switch
statements are for.
这就是switch语句的作用。
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
3
You might want to look at setjmp/longjmp.
您可能需要查看setjmp/longjmp。
#8
2
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.
你不能用goto -标签必须是标识符,而不是变量或常量。我不明白你为什么不愿意在这里使用开关——如果这是你所关心的,它很可能同样有效。
#9
1
For a simple answer, instead of forcing compilers to do real stupid stuff, learn good programming practices.
对于一个简单的答案,不要强迫编译器做真正的愚蠢的事情,学习好的编程实践。
#10
1
Tokenizer? This looks like what gperf was made for. No really, take a look at it.
记号赋予器吗?这看起来像gperf的作用。不,看看。
#11
1
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:
如果满足以下条件,优化编译器(包括GCC)将把一个switch语句编译成一个跳转表(使一个switch语句与您试图构建的东西一样快):
Your switch cases (state numbers) start at zero.
你的开关情况(状态数)从0开始。
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.)
有足够多的情况表明跳转表实际上更快(在处理switch语句的检查-case方法中,几十个比较-goto实际上比跳转表快)。
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.
这样做的好处是可以在标准C中编写代码,而不是依赖于编译器扩展。在GCC中,它的工作速度也一样快。在大多数优化编译器中,它的工作速度也一样快(我知道Intel编译器会这么做;不确定微软的东西)。它可以在任何编译器上工作,尽管速度较慢。