12

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:

  1. How do you work a goto?
  2. What are the constraints on gotos in C++?
  3. Any concerns about scope? (I'm going to try to globally scope as much as possible, but you never know.)
  4. If I use the GCC extension to goto to a void pointer array, are there any new concerns about undefined behavior, etc?


On longjmp:

  1. How would you safely use a longjmp?
  2. What are the constraints on longjmps in C++?
  3. What does it do to scope?
  4. 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?
  5. How would I simulate a computed goto with longjmp?
  6. 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.

Code Maker
  • 145
  • 1
  • 6
  • 7
    Cue deluge of non-answers condemning gotos in 3... 2... 1... – Justin ᚅᚔᚈᚄᚒᚔ Sep 28 '11 at 18:55
  • 17
    Thank you for attempting to proving that, literally, "real programmers can write FORTRAN in any language" :) –  Sep 28 '11 at 18:55
  • 5
    If you're writing "FORTRAN-esque" C++ then you're not writing C++. If I were in the bet then you'd have hard times convincing me you did your part. – wilhelmtell Sep 28 '11 at 18:57
  • 2
    Can we at least make fun of FORTRAN? – Ritch Melton Sep 28 '11 at 18:57
  • 1
    I think I used to work with this guy at my old job! – Didaxis Sep 28 '11 at 18:57
  • 3
    You can make fun of whatever you want, but if you post an answer I expect it to be a proper answer. Also, wilhelmtell, there were exact terms to our bet. – Code Maker Sep 28 '11 at 18:58
  • +1 for original question, although personally i think you are doing a creative attempt of getting answers for your homework. :) – AndersK Sep 28 '11 at 19:01
  • 2
    Anders K, I'm pretty sure these days there aren't really C++ teachers who _make_ you use gotos and longjmps. Usually they promise zeroes if you use them. And you haven't seen creative yet. I'm considering abusing the holy hell out of defines and overloading so that I won't even have to rewrite my FORTRAN. – Code Maker Sep 28 '11 at 19:09
  • that remembers me the day i implemented an Ada oriented exception handling mechanism in C, using gotos, longjmp and #defines... i had great fun writing and testing this, but was never able to use it in the real-world, fearing the wrath of my workmates. – Adrien Plisson Sep 28 '11 at 19:17
  • 3
    This *is* a real question. Just because you don't like `goto` is not a reason to close this post! – John Dibling Sep 28 '11 at 19:38
  • 4
    It's not difficult to tell what is being asked here. This question is not ambiguous, vague, incomplete, overly broad, or rhetorical and can be reasonably answered in its current form. When voting to close please don't pick a reason at random. – Troubadour Sep 28 '11 at 19:41
  • 6
    @John Dibling: I voted to close as *Not Constructive* because writing intentionally complex FORTRAN in C++ and soliciting swarms of "goto is bad" comments and debate is not helpful to anyone. – AJG85 Sep 28 '11 at 19:43
  • 2
    Related: http://stackoverflow.com/q/7334952/46642, http://stackoverflow.com/q/1376085/46642 and many others. – R. Martinho Fernandes Sep 28 '11 at 19:50
  • @AJG85, my intention can be nonconstructive, sure but my question is still perfectly constructive, and someone else looking at this question might have a more constructive purpose (like debugging someone else's code or whatever). – Code Maker Sep 28 '11 at 19:52
  • 4
    Here's what you should have tried **before asking this**: http://stackoverflow.com/questions/tagged/c%2b%2b%20longjmp and http://stackoverflow.com/questions/tagged/c%2b%2b%20goto – R. Martinho Fernandes Sep 28 '11 at 19:52
  • @R. Martinho Fernandes: Useful? Yes. Answering all parts of my question? No. – Code Maker Sep 28 '11 at 20:05
  • @CodeMaker: Why is this a question about C++? You are not using a single feature of C++ that isn't readily available in C. You aren't using objects, since everything is global. You're not using templates. You're not using reasonable structures of any kind. So what about this question makes it about C++? Indeed, being C++ means that you have the possibility to screw all kinds of things up that C cannot. – Nicol Bolas Sep 28 '11 at 22:07
  • @NicolBolas, I suppose because my good friend requested that I be coding it in C++, because the goto and longjmp still constitute a part of C++, and because I should have concerns about the behavior and requirements on gotos and longjmps in a C++ context where there might be subtle but crucial differences from how they would behave in C, which I am not doing. – Code Maker Sep 28 '11 at 22:11
  • "If I use the GCC extension to goto to a void pointer array, are there any new concerns about undefined behavior" <-- this is the point where my head asploded :^) – Jeremy Friesner Sep 28 '11 at 22:41
  • @NicolBolas: C++ has better type safety than C. – Janus Troelsen Sep 27 '12 at 20:26

7 Answers7

7

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 command goto 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 of goto targets but you can create an array of object or function pointers to jump to.

longjmp: There is no reason to prefer longjmp over goto 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.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
Mark B
  • 95,107
  • 10
  • 109
  • 188
  • 4
    Then your goal needs revision. – AJG85 Sep 28 '11 at 19:32
  • 3
    I don't see why my goal is your affair. The question is still legitimate. – Code Maker Sep 28 '11 at 19:46
  • 2
    @Code Maker: I just think this is more appropriate topic for the bar over some beers than a Q&A forum online. No one else will benefit from the answer, writing intentionally complex and convoluted code serves no real purpose, and frankly you're more likely to generate a `goto` witch hunt than get any real answers anyway. – AJG85 Sep 28 '11 at 19:54
  • 1
    @AJG85, "no one else will benefit from the answer" my foot. I am asking general questions about goto and longjmps. Anyone who needs to brush up on these things and is concerned about any specifics of their use would benefit from this question. – Code Maker Sep 28 '11 at 19:59
  • 2
    @CodeMaker You're asking general questions about gotp and longjmps that can easily be answered by reading documentation. If the "General Reference" close reason had been implemented already, I'd vote to close as that. *The* ideal answer to your question would basically be a rehash of that documentation. – R. Martinho Fernandes Sep 28 '11 at 20:00
  • Well it's not implemented atm, and "general reference" can be a fuzzy ground when there are compiler specific considerations, etc. at work. Like I just found out that GCC allows you to use void pointers for goto labels. That changes things. – Code Maker Sep 28 '11 at 20:13
  • @CodeMaker: A "general question about goto and longjmps" in C++ is answered very simple. "Use `goto` when not using `goto` would make your code more obfuscated than the `goto` does." And "`longjmp` annihilates automatic variables, so you should never use it in C++". How `goto` works is something any C++ book teaches. GCC extensions are expressly _not_ C++ and therefore are not a part of how `goto` works. So yes, everything you have asked for is general reference material, or has been asked and answered before. – Nicol Bolas Sep 28 '11 at 22:01
  • @NicolBolas: I am asking about performing computed goto type behavior and how to use longjmp in C++. And since you have so kindly stressed that longjmp does problematic things to C++ and therefore it's avoided, that makes it all the more important to know about the uses and risks of longjmp in C++, which do not appear to be well-documented. Incidentally, this question is flagged with the language-extension tag for a reason. – Code Maker Sep 28 '11 at 22:13
  • @CodeMaker: You can't document something that is _undefined behavior_, which is what the C++ specification says happens. Well, you could, but it would be useless documentation since it would change whenever you changed compilers. Or the phase of the moon. Or if a stiff breeze blew through the room. It's like asking what the behavior of accessing a deallocated piece of memory is. – Nicol Bolas Sep 28 '11 at 22:17
  • 1
    @NicolBolas True. And that proves we have gone beyond the scope of general reference. The longjmp still exists to be used, but the undocumented nature of its riskiness impels me to ask the question of what circumstances might non-intuitively cause problems and what considerations should be made to use it relatively safely. – Code Maker Sep 28 '11 at 22:28
4

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:

#include <iostream>
#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    int i = 0;
step:
    cout << "i = " << i;
    ++i;
    if( i < 10 )
        goto step;

}

In this case, step: is the label.

There are concerns about context.

  • You can only goto to a label within the current function.
  • If your 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.).
  • You cannot goto in to a try block or catch handler. However, you can goto out of a try 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.

Community
  • 1
  • 1
John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • Thanks. And I think you might have gotten me wrong here. What I meant to ask is "Can you have jump labels as pointers, arrays, or vectors for the purposes of the goto statement?" – Code Maker Sep 28 '11 at 19:31
  • 1
    OP says: "I don't usually code C++". Maybe expand "UB" acronym to "undefined behavior", or give a brief definition. – Robᵩ Sep 28 '11 at 19:33
  • @Code: You mean you want to store jump labels in a vector, for example? – John Dibling Sep 28 '11 at 19:34
  • @JohnDibling, by the way, do you know if a GCC void pointer label will do anything to these limits? – Code Maker Sep 28 '11 at 22:06
3

I think this reference has most of the information you are looking for.

goto

longjmp

ronag
  • 49,529
  • 25
  • 126
  • 221
  • 8
    I wouldn't call MSDN "the" reference, rather "a" reference :) (It states: "Describes the C++ programming language as implemented in Microsoft C++.") – Emile Vrijdags Sep 28 '11 at 19:15
3

computed goto --> switch

Really, they share a (common, but not universal) underling implementation as a jump table.

dmckee --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234
  • Only sometimes, if a switch has only a few choices then it will most likely be implemented as a series of if / else if statements instead. – Dominik Grabiec Sep 29 '11 at 03:30
  • Sure, and the compiler could choose the same implementation for a computed goto. – dmckee --- ex-moderator kitten Sep 29 '11 at 03:43
  • A switch statement only constitutes a forward jump. I could approximate the computed goto by doing a `computed_goto: switch (goto_variable) { ... }` before so I could do `goto_variable = 5; goto computed_goto;` but I'm hoping to use the longjmp() here. I remember doing that with Java though, only using a labelled while(true) loop and continue instruction instead, but alas Java isn't as Duff's device friendly. – Code Maker Sep 30 '11 at 07:27
1

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:

    GO TO (12,24,36), INDEX

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:

int SITU(int J, int K)
{
int raw_value = (J * 5) + K;

int index = (raw_value % 5) - 1;

return index;
}


int main(void)
{
int J = 5, K= 2;

// fortran computed goto statement: GO TO (320,330,340,350,360), SITU(J,K) + 1
switch (SITU(J,K) + 1)
{
case 0: // 320
    // code statement 320 goes here
    printf("Statement 320");
    break;
case 1: // 330
    // code statement 330 goes here
    printf("Statement 330");
    break;
case 2: // 340
    // code statement 340 goes here
    printf("Statement 340");
    break;
case 3: // 350
    // code statement 350 goes here
    printf("Statement 350");
    break;
case 4: // 360
    // code statement 360 goes here
    printf("Statement 360");
    break;
}

printf("\nPress Enter\n");
getchar();
return 0;
}

In this particular example, we see that you do not need C gotos to implement a FORTRAN computed goto!

Indinfer
  • 915
  • 9
  • 6
0

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.

Janus Troelsen
  • 20,267
  • 14
  • 135
  • 196
0

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. :)

John Humphreys
  • 37,047
  • 37
  • 155
  • 255
  • 5
    At the low low cost of completely undefined behavior in a lot of scenarios. – Billy ONeal Sep 28 '11 at 19:10
  • From all sounds of it he's trying to write complex code to win a bet - I would never touch goto or longjjmp in real code - they both are complex in the first place. :p – John Humphreys Sep 28 '11 at 19:13