如何将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]; } 

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

GCCfunction可以称为“ 标签作为值 ”。

 void *s[3] = {&&s0, &&s1, &&s2}; if (n >= 0 && n <=2) goto *s[n]; s0: ... s1: ... s2: ... 

它只适用于GCC!

goto需要一个编译时标签。

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

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

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

没有直接的方法来存储代码地址以跳转到C.如何使用开关。

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

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

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

这样你就可以创建一个函数数组来调用和调用适当的函数。

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

扩展引入了new运算符&& ,以获取标签的地址,然后可以与goto语句一起使用。

这就是switch语句的用途。

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

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

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

你可能想看看setjmp / longjmp。

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

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

标记生成器? 这看起来像是为什么制造了gperf。 不,真的,看看它。

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

您的开关案例(州号)从零开始。

您的开关箱严格增加。

在切换案例中,不要跳过任何整数。

有足够的情况,跳转表实际上更快(在检查 – 处理switch语句的每种情况下方法中的几十个比较和结果实际上比跳转表更快。)

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