如何在 C++ 中(计算)goto 和 longjmp?
我通常不编写 C++ 代码,但我的一位奇怪的计算机科学朋友厌倦了查看我精彩的 FORTRAN 程序,并挑战我用 C++ 重写其中一个程序,因为他更喜欢我的 C++ 代码。 (我们在这里赌钱。)确切地说,它需要可以在现代 C++ 编译器中编译。也许他讨厌一个好的 conio.h - 我不知道。
现在我意识到用 C++ 编写有一些非常好的方法,但我想通过尝试使我的 C++ 版本尽可能像 FORTRAN 风格来获得个人胜利。作为奖励积分,这可能会在我转换代码时节省一些时间和精力。
所以!这让我想到以下相关问题:
关于 goto:
- 你如何使用 goto?
- C++ 中 goto 的限制是什么?
- 对范围有任何疑问吗? (我将尝试尽可能地覆盖全局范围,但你永远不知道。)
- 如果我使用 GCC 扩展转到 void 指针数组,是否有关于未定义行为等的新问题?
关于longjmp:
- 您将如何安全地使用longjmp?
- C++ 中的 longjmp 有哪些限制?
- 它对范围有什么作用?
- 是否有任何特定时刻看起来 longjmp 应该是安全的,但实际上我不应该注意?
- 如何使用 longjmp 模拟计算的 goto?
- 如果我的程序中只有一个函数,那么使用 longjmp 相对于 goto 是否有任何实际好处?
现在我主要关心的是让计算 goto 能够实现这一点。看起来我可能会使用 longjmp 来完成这项工作,因为 void 指针数组不是 C++ 标准的一部分,但是GCC 特定扩展。
I don't usually code C++, but a strange comp sci friend of mine got sick of looking at my wonderful FORTRAN programs and challenged me to rewrite one of them in C++, since he likes my C++ codes better. (We're betting money here.) Exact terms being that it needs to be compilable in a modern C++ compiler. Maybe he hates a good conio.h - I don't know.
Now I realize there are perfectly good ways of writing in C++, but I'm going for a personal win here by trying to make my C++ version as FORTRAN-esque as possible. For bonus points, this might save me some time and effort when I'm converting code.
SO! This brings me to the following related queries:
On gotos:
- How do you work a goto?
- What are the constraints on gotos in C++?
- Any concerns about scope? (I'm going to try to globally scope as much as possible, but you never know.)
- If I use the GCC extension to goto to a void pointer array, are there any new concerns about undefined behavior, etc?
On longjmp:
- How would you safely use a longjmp?
- What are the constraints on longjmps in C++?
- What does it do to scope?
- Are there any specific moments when it looks like a longjmp should be safe but in fact it isn't that I should watch out for?
- How would I simulate a computed goto with longjmp?
- Is there any tangible benefit to using longjmp over goto if I only have one function in my program?
Right now my main concern is making a computed goto work for this. It looks like I'll probably use the longjmp to make this work because a void pointer array isn't a part of the C++ standard but a GCC specific extension.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我会咬紧牙关并投下反对票。
我严重怀疑你的朋友会发现用 C++ 编写的 Fortran 更容易阅读(如果你大量使用 goto 和 longjmp,这实际上是你会得到的),他甚至可能会发现更难理解。 C++ 语言与 Fortran 有很大不同,我真的不认为您应该尝试从 Fortran 直接转换为 C++。它只会使 C++ 更难维护,您还不如继续使用现有的代码库。
goto
:您设置一个标签 (my_label:
),然后使用 goto 命令goto my_label;
这将使您的程序流程执行于goto 后面的语句。您无法跳过变量的初始化或函数之间的初始化。您无法创建一个goto
目标数组,但您可以创建一个要跳转到的对象或函数指针数组。longjmp
:如果您只有一个函数,则没有理由选择longjmp
而不是goto
。但是,如果您只有一个函数,那么您实际上并不是在编写 C++,从长远来看,您只需维护 Fortran 就会更好。I'll bite and take the downvote.
I seriously doubt that your friend will find Fortran written in C++ any easier (which is effectively what you'll get if you use goto and longjmp significantly) to read and he might even find it harder to follow. The C++ language is rather different from Fortran and I really don't think you should attempt a straight conversion from Fortran to C++. It will just make the C++ harder to maintain and you might as well stay with your existing codebase.
goto
: You set up a label (my_label:
) and then use the goto commandgoto my_label;
which will cause your program flow to execute at the statement following the goto. You can't jump past the initialization of a variable or between functions. You can't create an array ofgoto
targets but you can create an array of object or function pointers to jump to.longjmp
: There is no reason to preferlongjmp
overgoto
if you have only one function. But if you have only one function, again, you really aren't writing C++ and you'll be better off in the long run just maintaining your Fortran.你会因为使用
goto
而受到很多仇恨。通常情况下,我会紧跟潮流,但在这种特殊情况下,对我来说,这听起来更像是代码高尔夫。那么就到这里吧。使用
goto
将指令指针移动到代码中的“标签”,该“标签”是一个 C++ 标识符,后跟一个冒号。下面是一个工作程序的简单示例:在本例中,
step:
是标签。人们对背景感到担忧。
goto
到当前函数内的标签。goto
跳过变量的初始化,您可能会引发未定义行为 (可以编译的代码,但你不能确定它实际上会做什么。)。goto
进入try
块或catch
处理程序。但是,您可以转到
出try
块。只要满足其他问题,您就可以使用指针等“转到”。如果有问题的指针在调用站点的范围内并且在分支站点的范围内,则没有问题。
You'll get plenty of haterade about using
goto
at all. Normally I'd jump right on the bandwagon, but in this particular case it sounds more like code golf to me. So here you go.Use
goto
to move the instruction pointer to a "label" in your code, which is a C++ identifier followed by a colon. Here's a simple example of a working program:In this case,
step:
is the label.There are concerns about context.
goto
to a label within the current function.goto
skips the initialization of a variable, you may evoke Undefined Behavior (Code which will compile, but you can't say for sure what it will actually do.).goto
in to atry
block orcatch
handler. However, you cangoto
out of atry
block.You "can goto" with pointers etc provided the other concerns are met. If the pointer in question is in-scope at the call site and in-scope at the branch site, no problem.
我认为此参考资料包含您正在寻找的大部分信息。
转到
longjmp
I think this reference has most of the information you are looking for.
goto
longjmp
计算出的
goto
-->switch
实际上,它们共享一个(通用的,但不是通用的)底层实现作为跳转表。
computed
goto
-->switch
Really, they share a (common, but not universal) underling implementation as a jump table.
如果我理解了原来的问题,这个问题实际上是一个有趣的问题。重新表述这个问题(我认为是一个等效的问题):“如何在 C 中执行 FORTRAN 计算 goto?”
首先,我们需要知道什么是计算转到:以下是一个解释的链接:http://h21007.www2.hp.com/portal/download/files/unprot/fortran/docs/lrm/lrm0124.htm。
计算 GOTO 的一个示例是:
其中 12、24 和 36 是语句编号。 (C 语言标签可以作为等价物,但不是唯一可以等价的东西。)
其中 INDEX 是变量,但可以是公式的结果。
这是在 C 中执行相同操作的一种方法(但不是唯一的方法):
在这个特定示例中,我们看到您不需要 C goto 来实现 FORTRAN 计算 goto!
If I understand the original question, the question is actually an interesting one. Rewording the question (to what I think is an equivalent question): "How do you do a FORTRAN computed goto in C?"
First we need to know what a computed goto is: Here is a link to one explanation: http://h21007.www2.hp.com/portal/download/files/unprot/fortran/docs/lrm/lrm0124.htm.
An example of a computed GOTO is:
Where 12, 24, and 36 are statement numbers. (C language labels could serve as an equivalent, but is not the only thing that could be an equivalent.)
And where INDEX is a variable, but could be the result of a formula.
Here is one way (but not the only way) to do the same thing in C:
In this particular example, we see that you do not need C gotos to implement a FORTRAN computed goto!
Longjmp 可以让您摆脱信号处理程序,这可能很好 - 但它会增加一些混乱,因为它不会重置它长跳转到 setjmp 行之前定义的函数中的自动(基于堆栈的)变量。 :)
Longjmp can get you out of a signal handler which can be nice - and it'll add some confusion as it will not reset automatic (stack-based) variables in the function it long jumps to defined prior to the setjmp line. :)
有一个名为 标签作为值< 的 GCC 扩展/strong> 这将帮助您编写高尔夫代码,本质上是为您提供计算的转到。当然,您可以自动生成标签。您可能需要这样做,因为您无法知道每行将生成多少字节的机器代码。
There is a GCC extension called Labels as Values that will help you code golf, essentially giving you computed goto. You can generate the labels automatically, of course. You will probably need to do that since you can't know how many bytes of machine code each line will generate.