5

Is there a way to call a goto statement using a variable in the place of a label name?

I'm looking for something similar to this (this doesn't work for me):

// std::string or some other type that could represent a label
void callVariable(std::string name){
    goto name;
}

int main(){
    first:
    std::cout << "Hi";
    callVariable(first);

    return 0;
}

I am not actually using this, I am more interested in learning.

esote
  • 831
  • 12
  • 25
  • 4
    gotos are bad mkay? – Guillaume Racicot Sep 03 '16 at 00:11
  • I teach that a goto can always be replaced by a function call and a little rewrite, but this is an interesting construct -- dynamic branching I guess. I'd never use it but it's fun to talk about. – nicomp Sep 03 '16 at 00:15
  • Sometimes beginners ask interesting questions. That is an interesting approach. But what you want is a `switch` statement. – Steve Wellens Sep 03 '16 at 00:17
  • 2
    @nicomp Yeah I totally understand that gotos are not optimal in almost all use-cases. I am approaching this from more of a learning standpoint, wondering how this could be done. – esote Sep 03 '16 at 00:18
  • 2
    @nicomp gotos are well adapted for old, ugly and outdated code. sure it can save you a lot of time in that case. It's just that today with features like lamdas, you barely need it anymore. But as they exist, it's important to know them, and learn why not use them. – Guillaume Racicot Sep 03 '16 at 00:19
  • FORTRAN had a computed go to. Don't know if it still does. – Pete Becker Sep 03 '16 at 00:37
  • @PeteBecker: Someone, possibly you, once mentioned Intercal's computed `COMEFROM`. :) – Cheers and hth. - Alf Sep 03 '16 at 00:41
  • @Cheersandhth.-Alf -- I hadn't seen that before. Very avant garde. I did see an article about BASIC once that mentioned COMEFROM, as well as WHOA, which you were supposed to use to warn the compiler to slow down for some really tricky code. – Pete Becker Sep 03 '16 at 01:27
  • @Pete Becker - From memory, computed goto was put onto the obsolescent list in Fortran 95. I'm not sure if it has been deleted in a later standard. – Peter Sep 03 '16 at 12:17
  • goto are great when you are programatically generating code, for example for a language parser. When humans don't need to manually maintain the code, goto can help a lot. – vz0 Sep 09 '16 at 11:21
  • Does this answer your question? [Can you make a computed goto in C++](https://stackoverflow.com/questions/45380073/can-you-make-a-computed-goto-in-c) – phuclv Nov 01 '20 at 12:10

5 Answers5

14

Yes and no. There's no such standard language feature, but it is a compiler extension in at least GCC:

int main() {
    void* label;

    first:
    std::cout << "Hi";
    label = &&first;
    goto *label;
}

That said, I'd have to think hard for a use case where this is better than any standard alternatives.

chris
  • 60,560
  • 13
  • 143
  • 205
  • plusone . . . easily the coolest hack I've seen all year. Not something I would (or should) ever use but still pretty neat. – sparc_spread Sep 03 '16 at 00:12
  • @sparc_spread IMHO "clever" and "tricky" code that will confuse most readers is *not* a good thing. Leave "clever" to the compiler and write clear, readable code. Trying to be too clever and using obscure corners of the language is IMHO more a sign of a bad programmer than anything else.. – Jesper Juhl Sep 03 '16 at 00:16
  • 2
    @sparc_spread: This is not a hack. It's a language extension. – Cheers and hth. - Alf Sep 03 '16 at 00:20
  • 2
    @Jesper Juhl That's what the "not . . . would (or should) ever use" disclaimer part was about :-) – sparc_spread Sep 03 '16 at 00:20
  • 1
    @Anonymous, The function would have to be a macro. `goto` doesn't work across different functions. – chris Sep 03 '16 at 01:28
  • @chris For a possible use case: I can think of one. This would serve to efficiently execute 2 or more concurrent (in logic only) finite state machines. You store the state of each FSM in a variable, and from time to time, you do a sort of context switch where you jump from one fsm to another, but directly at the state it was in the previous time. Then you "return" to the main fsm – WhiteMist Feb 17 '22 at 19:37
4

You ask:

Is there a way to call a goto statement using a variable in the place of a label name?

Yes, the feature in C++ that provides that effect is called switch. It doesn't syntactically involve the word goto. But it jumps to a label specified by a variable, and so, with it you can emulate all kinds of dirty goto-based code, including early Basic's on ... goto ....


Your hypothetical example

int main(){
    first:
    std::cout << "Hi";
    callVariable(first);

    return 0;
}

… looks like this in real C++:

#define CALL_VARIABLE( where ) next_jump = where; break;

auto main()
    -> int
{
    enum Label {first, second, third};
    Label next_jump = first;
    for( ;; ) switch( next_jump )
    {
    case first:
        std::cout << "Hi";
        CALL_VARIABLE( first );
    }
}
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
3

Short answer: no.

Long answer: no. And why would you want this? Just stop using goto already.

Maybe (just guessing) what you want is a std::function or a switch instead..

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
  • 3
    `goto` isn't always bad, some constructs for embedded to allow a program to always have the same exit point make the code neater and safer (especially when exceptions are not available or too expensive) . – Fantastic Mr Fox Sep 03 '16 at 00:42
  • 3
    Sure, for C code it can be useful for "single-exit-point-cleanup" blocks and other similar constructs. I'm not trying to say it is *always* bad; just that for C++ code there are usually better alternatives. I've done enough Linux kernel patches to recognize that (especially) in C it can be useful for exit blocks.. but I'd hessitate to use it in modern C++. – Jesper Juhl Sep 03 '16 at 00:45
2

this is a simple macro solution:

#define CALL_VARIALBLE(name) goto name;

int main(){
    first:
    std::cout << "Hi";
    CALL_VARIALBLE(first);

    return 0;
}
rahnema1
  • 15,264
  • 3
  • 15
  • 27
2

You can't goto a dynamic location.

But you can have a look at POSIX setjmp/longjmp, which can be used to jump to a predefined location in your application. MSVC also supports it.

#include <stdio.h>
#include <setjmp.h>

static jmp_buf buf;

void second(void) {
    printf("second\n");         // prints
    longjmp(buf,1);             // jumps back to where setjmp was called - making setjmp now return 1
}

void first(void) {
    second();
    printf("first\n");          // does not print
}

int main() {   
    if (!setjmp(buf))
        first();                // when executed, setjmp returned 0
    else                        // when longjmp jumps back, setjmp returns 1
        printf("main\n");       // prints

    return 0;
}
rustyx
  • 80,671
  • 25
  • 200
  • 267