我想使用longjmp来模拟goto指令。我有一个包含struct类型元素的数组DS(int,float,bool,char)。我想跳到标有“lablex”的地方,其中x是DS [TOP] .int_val。我怎么处理这个?
示例代码:
...
jmp_buf *bfj;
...
stringstream s;s<<"label"<<DS[TOP].int_val;
bfj = (jmp_buf *) s.str();
longjmp(*bfj,1);
但是我认为它有问题我该怎么办?
错误:
output.cpp:在函数'int main()'中:
output.cpp:101:错误:从'std :: basic_string,std :: allocator&gt;'类型无效转换为'__jmp_buf_tag(*)[1]'
答案 0 :(得分:5)
使用longjump的常规方法是与here所述的setjump()组合。您似乎想像通常使用switch-case或使用虚函数一样进行跳转。
无论如何,代码(编译时)中的标签不能用字符串(运行时)访问,所以这已经是你的第一个问题了。你真的需要找出你想要跳转到的地址,我最好的猜测就是将setjump()放在标签的位置。
答案 1 :(得分:5)
你可能根本不想使用longjmp,但是当人们用“你为什么要这样做?”回答问题时我讨厌它。正如已经指出你的 longjmp()用法是错误的。这是一个如何正确使用它的简单示例:
#include <setjmp.h>
#include <iostream>
using namespace std;
jmp_buf jumpBuffer; // Declared globally but could also be in a class.
void a(int count) {
// . . .
cout << "In a(" << count << ") before jump" << endl;
// Calling longjmp() here is OK because it is above setjmp() on the call
// stack.
longjmp(jumpBuffer, count); // setjump() will return count
// . . .
}
void b() {
int count = 0;
cout << "Setting jump point" << endl;
if (setjmp(jumpBuffer) == 9) return;
cout << "After jump point" << endl;
a(count++); // This will loop 10 times.
}
int main(int argc, char *argv[]) {
b();
// Note: You cannot call longjmp() here because it is below the setjmp() call
// on the call stack.
return 0;
}
使用longjmp()的问题如下:
但实际上,您根本不可能使用 longjmp()。
答案 2 :(得分:2)
你完全失败的C ++。首先,goto是坏的,而不是没有经验的 - 有一个原因,因为,while,break,continue等存在。其次,您正在尝试将字符串转换为标识符,这在运行时是不可能的,除非您自己编写代码。第三,你是......试图将一个const char *转换为jmp_buf *?什么?
除此之外,C ++确实有goto。但是如果你想跳转给定一个int,那么你将不得不切换它,例如。
switch (DS[TOP].int_val) {
case 1:
goto label1;
break;
case 2:
goto label2;
break;
default:
throw std::runtime_error("Unrecognized label!");
}
答案 3 :(得分:0)
听起来你想要一个函数指针:
((void(*)(void))*((int *)DS[TOP].int_val))();
这会将DS [TOP] .int_value视为地址并跳转到该地址。如果你想跳到DS [TOP] .int_value所在的位置,你会:
((void(*)(void))*((int *)&DS[TOP].int_val))();
无论哪种方式,丑陋,丑陋的代码。但它应该做你想要的。
答案 4 :(得分:0)
调用setjmp()时,系统会有效地获取调用和参数堆栈的快照。在用户代码退出调用setjmp()的块之前,此快照将保持有效;如果使用该快照调用longjmp(),则执行将恢复,就像setjmp()第一次返回一样,除了不返回零,它将返回传递给longjmp()的第二个参数。请注意,使用无效快照调用longjmp()可能会产生非常糟糕的影响,这一点非常重要。在某些系统中,这样的无效调用可能“似乎”起作用,但会以稍后崩溃的方式破坏系统。
尽管setjmp()/ longjmp()有时适用于纯C程序,但让C程序调用setjmp()来创建快照,然后调用一些C ++代码,然后调用longjmp()返回到该快照,是灾难的秘诀。几乎所有人都希望这样做的情况可以通过例外来更好地处理。