如何将 goto 标签存储在数组中然后跳转到它们?
我想声明一个“jumplabels”数组。
然后我想跳转到这个数组中的一个“jumplabel”。
但我不知道该怎么做。
它应该类似于以下代码:
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];
}
有谁知道如何执行此操作?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
使用称为“标签作为值”的 GCC 功能是可能的。
它仅适用于 GCC!
It is possible with GCC feature known as "labels as values".
It works only with GCC!
goto
需要一个编译时标签。从这个例子来看,您似乎正在实现某种状态机。 最常见的是,它们被实现为 switch-case 结构:
如果您需要它更加动态,请使用函数指针数组。
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:
If you need it to be more dynamic, use an array of function pointers.
在 C 中没有直接的方法来存储要跳转到的代码地址。
使用开关怎么样。
您可以找到每个无堆栈解析器/状态机生成器生成的类似代码。
这样的代码不容易理解,所以除非它是生成的代码,否则你的问题是最严重的
很容易用状态机描述我建议不要这样做。
There's no direct way to store code addresses to jump to in C.
How about using switch.
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.
你能用函数指针代替 goto 吗?
这样您就可以创建一组函数来调用并调用适当的函数。
could you use function pointers instead of goto?
That way you can create an array of functions to call and call the appropriate one.
据我所知,在普通标准 C 中这是不可能的。 然而,GCC 编译器中有一个扩展,记录在案在这里,这使得这成为可能。
该扩展引入了新的运算符
&&
,用于获取标签的地址,然后可以将其与goto
语句一起使用。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 thegoto
statement.这就是
switch
语句的用途。请注意,编译器不一定将其转换为跳转表。
如果您确实想自己构建跳转表,可以使用函数指针数组。
That's what
switch
statements are for.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.
您可能想查看 setjmp/longjmp。
You might want to look at setjmp/longjmp.
你不能用 goto 来做到这一点 - 标签必须是标识符,而不是变量或常量。 我不明白为什么你不想在这里使用开关 - 如果这是你所关心的,它可能会同样有效。
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.
对于一个简单的答案,不要强迫编译器做真正愚蠢的事情,而是学习良好的编程实践。
For a simple answer, instead of forcing compilers to do real stupid stuff, learn good programming practices.
分词器? 这看起来就像 gperf 的用途。 实在不行,看一下吧。
Tokenizer? This looks like what gperf was made for. No really, take a look at it.
如果满足以下条件,优化编译器(包括 GCC)会将 switch 语句编译到跳转表中(使 switch 语句与您尝试构造的内容一样快):
您的 switch 情况(状态编号)从零开始。
您的开关盒正在严格增加。
您不会跳过 switch case 中的任何整数。
有足够多的情况表明跳转表实际上更快(处理 switch 语句的检查每种情况方法中的几十个比较和跳转实际上比跳转表更快。)
这样做的优点是允许您使用标准 C 编写代码,而不是依赖编译器扩展。 它在 GCC 中的运行速度同样快。 它在大多数优化编译器中也能同样快速地工作(我知道英特尔编译器可以做到这一点;不确定微软的东西)。 尽管速度较慢,但它可以在任何编译器上运行。
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.