如何将 goto 标签存储在数组中然后跳转到它们?

发布于 2024-07-23 12:14:30 字数 337 浏览 10 评论 0原文

我想声明一个“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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

人生百味 2024-07-30 12:14:30

使用称为“标签作为值”的 GCC 功能是可能的。

void *s[3] = {&&s0, &&s1, &&s2};

if (n >= 0 && n <=2)
    goto *s[n];

s0:
...
s1:
...
s2:
...

它仅适用于 GCC!

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!

苏辞 2024-07-30 12:14:30

goto 需要一个编译时标签。

从这个例子来看,您似乎正在实现某种状态机。 最常见的是,它们被实现为 switch-case 结构:

while (!finished) switch (state) {
  case s0:
  /* ... */
  state = newstate;
  break;

  /* ... */
}

如果您需要它更加动态,请使用函数指针数组。

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.

謌踐踏愛綪 2024-07-30 12:14:30

在 C 中没有直接的方法来存储要跳转到的代码地址。
使用开关怎么样。

#define jump(x)  do{ label=x; goto jump_target; }while(0)
int label=START;
jump_target:
switch(label)
{
    case START:
        /* ... */
    case LABEL_A:
        /* ... */
}

您可以找到每个无堆栈解析器/状态机生成器生成的类似代码。
这样的代码不容易理解,所以除非它是生成的代码,否则你的问题是最严重的
很容易用状态机描述我建议不要这样做。

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.

简单 2024-07-30 12:14:30

你能用函数指针代替 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.

很快妥协 2024-07-30 12:14:30

据我所知,在普通标准 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 the goto statement.

情域 2024-07-30 12:14:30

这就是 switch 语句的用途。

switch (var)
{
case 0:
    /* ... */
    break;
case 1:
    /* ... */
    break;
default:
    /* ... */
    break;  /* not necessary here */
}

请注意,编译器不一定将其转换为跳转表。

如果您确实想自己构建跳转表,可以使用函数指针数组。

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.

晨与橙与城 2024-07-30 12:14:30

您可能想查看 setjmp/longjmp。

You might want to look at setjmp/longjmp.

花间憩 2024-07-30 12:14:30

你不能用 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.

初见终念 2024-07-30 12:14:30

对于一个简单的答案,不要强迫编译器做真正愚蠢的事情,而是学习良好的编程实践。

For a simple answer, instead of forcing compilers to do real stupid stuff, learn good programming practices.

许你一世情深 2024-07-30 12:14:30

分词器? 这看起来就像 gperf 的用途。 实在不行,看一下吧。

Tokenizer? This looks like what gperf was made for. No really, take a look at it.

深海蓝天 2024-07-30 12:14:30

如果满足以下条件,优化编译器(包括 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文