22

我想声明一个“跳转标签”数组。

然后我想跳转到这个数组中的一个“跳转标签”。

但我不知道如何做到这一点。

它应该类似于以下代码:

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

有谁知道如何执行此操作?

4

11 回答 11

44

GCC 功能称为“标签即值”是可能的。

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

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

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

它仅适用于 GCC!

于 2009-06-02T08:49:58.817 回答
17

goto需要一个编译时标签。

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

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

  /* ... */
}

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

于 2009-06-02T08:41:23.827 回答
12

在 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:
        /* ... */
}

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

于 2009-06-02T08:40:26.107 回答
8

你可以使用函数指针而不是 goto 吗?

这样,您可以创建一组函数来调用并调用适当的函数。

于 2009-06-02T08:40:51.643 回答
6

据我所知,在普通的标准 C 中,这是不可能的。然而,GCC 编译器中有一个扩展,记录在这里,这使得这成为可能。

该扩展引入了新的操作符&&,用于获取标签的地址,然后可以将其与goto语句一起使用。

于 2009-06-02T08:41:01.487 回答
5

这就是switch声明的用途。

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

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

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

于 2009-06-02T08:42:09.907 回答
4

您可能想查看 setjmp/longjmp。

于 2009-06-02T11:36:56.123 回答
2

你不能用 goto 来做——标签必须是标识符,而不是变量或常量。我不明白你为什么不想在这里使用开关——如果这与你有关的话,它可能同样有效。

于 2009-06-02T08:42:20.453 回答
1

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

于 2009-06-02T08:47:22.190 回答
1

分词器?这看起来像是 gperf 的用途。不,真的,看看它。

于 2009-06-07T10:00:04.037 回答
1

如果满足以下条件,优化编译器(包括 GCC)会将 switch 语句编译到跳转表中(使 switch 语句与您尝试构建的东西一样快):

您的开关案例(状态编号)从零开始。

您的开关盒正在严格增加。

您不会在 switch 案例中跳过任何整数。

有足够多的情况表明跳转表实际上更快(在处理 switch 语句的检查每个案例方法中的几十个比较和转到实际上比跳转表更快。)

这样做的好处是允许您用标准 C 编写代码,而不是依赖编译器扩展。它在 GCC 中的运行速度也一样快。它在大多数优化编译器中的运行速度也一样快(我知道英特尔编译器可以做到这一点;不确定微软的东西)。它可以在任何编译器上工作,尽管速度较慢。

于 2016-04-16T18:25:18.427 回答