Can I jump to a case inside a switch using goto?

R

rivkaumiller

while((c=getchar())!=EOF){

switch(flower){
case rose:
switch(color){
case white:
// do something 1
case pink:
// do something 2
...
}
case lily:
switch(color){
case white:
// do something 1
case pink:
// do something 2

...
}
...
case unique:
// do something 3
...
}
}


basically, I can write the above statement completely using
if(flower==rose) goto
if(color==white) goto

type statements.

unfortunately, some of the flowers have strange names such as the ascii value of '/' or other characters like '%' and so on so switch-case gives me brevity.

However, inside switch-case I want to jump to certain cases before breaking to the end.

for example from (rose,pink) I may want to goto unique: . Can I do that by a

goto unique: ?

Note its a unique label. It is also an alias for another case where I want to do something unique before going into the while cycle which will read a char and then break down to the end.

I have a few choices.

One is that I have that label outside both of the switch-cases and its not a switch case label. There, if I want to fall through the cases below, I will have to use goto end: for all of them.

However, I can also put some dummy labels with break in the outermost switch-case and use them as labels.

In crux, the question is if I can use a switch-case's case-colon as a label for goto or not?

If so, then can I use a case like '%'-colon as a case for goto using

goto '%' ?

Thanks
 
K

Keith Thompson

In crux, the question is if I can use a switch-case's case-colon as a
label for goto or not?
[snip]

No, you can't. The target of a goto must be a the name of a label
defined with the "identifer ": syntax; a case label doesn't qualify.

You can always add labels as needed:

switch (...) {
case 0:
L0:
/* ... */
break;
case 1:
L1:
/* ... */
break;
/* ... */
default:
Default:
/* ... */
break;
}
/* ... */
goto L1;
goto L2;
goto Default;

But I'd really advise you to rethink your design. Careful use of goto
statements, usually to a pointer *later* in the code, can be useful for
error handling and for breaking out of nested loops, but heavy use of
gotos can easily result in spaghetti code.

If you're implementing a finite state machine, I suggest either a switch
statement in a loop, where the switch executes some chunk of code
depending on the current state, *or* a sequence of labelled blocks with
gotos. (I personally prefer the former; for one thing, encoding the
current state in a variable rather than having it be implicit in the
current location in the program can be helpful). Mixing case labels and
gotos could easily get out of control.
 
R

rivkaumiller

Keith Thompson said:
(e-mail address removed) writes:
In crux, the question is if I can use a switch-case's case-colon as a
label for goto or not?

No, you can't. The target of a goto must be a the name of a label
defined with the "identifer ": syntax; a case label doesn't qualify.

You can always add labels as needed:

If you're implementing a finite state machine, I suggest either a switch
statement in a loop, where the switch executes some chunk of code
depending on the current state, *or* a sequence of labelled blocks with
gotos. (I personally prefer the former; for one thing, encoding the
current state in a variable rather than having it be implicit in the
current location in the program can be helpful). Mixing case labels and
gotos could easily get out of control.

Wil... , you seem to cover a number of topics rapidly in your reply. Unfortunately, google does not give an option to email you either.

What is computed goto and which languages have it?
It's a shame the committee never took up computed gotos. For complex state

machines you often need to jump around. Sure, you can set the next state and

break out of the switch statement. But often times code will be nested

inside loops, so you need to use a goto, anyhow, to break out. And that goto

often takes you back to the _top_ of some outer loop.

I wanted to see some examples.
Plus, if you care about performance, you want to try to thread your

instructions to avoid the loop conditional. I suppose it's possible with

switch statements, as long as your compiler is smart enough, but computed

gotos make it so much easier.

Again some concrete examples would clarify the vision in your mind.
I've had some success with macro solutions which hide two

specific macros and the example?
implementations--one using switch and another computed gotos. With GCC and

clang computed goto machines are always significantly faster. (And I never

use GCC's recommendation of storing label offsets, because that's a gigantic

pain in the butt--impossible if you generate cases or labels with

__LINE__--and in the age of C++ nobody will notice the insignicant link-time

costs.)

Again, more writing is needed to clarify your point and generate benefit.
 
R

rivkaumiller

(e-mail address removed) writes:

[snip]
In crux, the question is if I can use a switch-case's case-colon as a
label for goto or not?

[snip]



No, you can't. The target of a goto must be a the name of a label

defined with the "identifer ": syntax; a case label doesn't qualify.



You can always add labels as needed:



switch (...) {

case 0:

L0:

/* ... */

break;

case 1:

L1:

/* ... */

break;

/* ... */

default:

Default:

/* ... */

break;

}

/* ... */

goto L1;

goto L2;

goto Default;



But I'd really advise you to rethink your design. Careful use of goto

statements, usually to a pointer *later* in the code, can be useful for

error handling and for breaking out of nested loops, but heavy use of

gotos can easily result in spaghetti code.



If you're implementing a finite state machine, I suggest either a switch

statement in a loop, where the switch executes some chunk of code

depending on the current state, *or* a sequence of labelled blocks with

gotos. (I personally prefer the former; for one thing, encoding the

current state in a variable rather than having it be implicit in the

current location in the program can be helpful). Mixing case labels and

gotos could easily get out of control.

Thanks. I understood all your points except this one.

"for one thing, encoding the
current state in a variable rather than having it be implicit in the

current location in the program can be helpful)"

How can it be helpful? what are the comparative limitations of each approach?

Second, can you try to make sense of the points made by wil... , the next poster?
 
S

Stefan Ram

Can I jump to a case inside a switch using goto?

#include <stdio.h>

int main()
{ int pc = 3;
#define GOTO(x) pc=x;break
while( 1 )switch( pc )
{ case 2: puts( "2:" ); goto out;
case 3: puts( "3:" ); GOTO( 2 ); }
out:; }
 
J

JohnF

Keith Thompson said:
can I use a switch-case's case-colon as a
label for goto or not?
[snip]

No, you can't.
You can always add labels as needed:
switch (...) {
case 0:
L0: /* ... */ break;
case 1:
L1: /* ... */ break;
/* ... */
default:
Default: /* ... */ break;
} /* --- end-of-switch() --- */
/* ... */
goto L0;
goto L1;
goto Default;
But I'd really advise you to rethink your design.

Yeah, that's for sure. But just curious -- if one
of those goto's takes execution from outside the
switch's {...} to inside it, will the subsequent
break understand the scope, i.e., where the program
counter should go next? And is that behavior mandated
by standard?
 
S

Stefan Ram

#define GOTO(x) pc=x;break

#include <stdio.h>

int main()
{ for( int pc = 3; pc; )switch( pc )
{ case 2: puts( "2:" ); pc = 0; break;
case 3: puts( "3:" ); pc = 2; break; }}
 
R

rivkaumiller

#include <stdio.h>
int main()
{ int pc = 3;
#define GOTO(x) pc=x;break

while( 1 )switch( pc )
{ case 2: puts( "2:" ); goto out;
case 3: puts( "3:" ); GOTO( 2 ); }
out:; }

but you are going through the while loop head to do the GOTO.
In my case, there is a getchar() there so an input stream has been consumed. You are not allowed to go through the loop head.
 
G

glen herrmannsfeldt

On Wednesday, April 2, 2014 8:02:17 PM UTC-7, [email protected] wrote: (snip)

What is computed goto and which languages have it?

As far as I know, it started with Fortran I in 1956.

GOTO (10, 20, 30, 40, 50, 60), J

Goes to the first statement number if J is 1, the second if J is 2,
and so on. In early Fortran (before 1977) it was undefined if J
was less than 1 or greater than the number of labels. Many as an
extension, and added in Fortran 77, if J is out of range, it goes
to the following statement.

Many BASIC systems implement computed GOTO as

100 ON J GOTO 10, 20, 30, 40, 50, 60

PL/I has LABEL variable arrays, which can either be initialized
with the appropriate labels on the DECLARE, or by specifying an
array element as a statement label. The latter doesn't look so
different from switch/case.

DCL X(5) LABEL INITIAL(ONE, TWO, THREE);

or:

DCL Y(5) LABEL;

then label statements such as:

Y(3): PUT LIST('Three');


Then GOTO X(I); or GOTO Y(J); will go to the appropriate statement.

I think ALGOL-68 has one, but I am not sure. The description is
in its own language, and not so easy to figure out.

As I happen to have a COBOL manual nearby, though haven't actually
written any programs, it seems to have:

GOTO labels DEPENDING ON variable.


-- glen
 
S

Stefan Ram

glen herrmannsfeldt said:
100 ON J GOTO 10, 20, 30, 40, 50, 60

»ON J GOSUB 10, 20« in BASIC becomes »gosub[ j ]();« in C,
where »gosub« is an array of function pointers.
 
M

Malcolm McLean

What is computed goto and which languages have it?
Fortran has it.
Minibasic http://sourceforge.net/directory/?q=minibasic also has it.

You use integers for lablels, then goto x; is allowed, where x is an integer
variable. In Minibasic, is was a simply a case of writing the parser as
goto (expression) rather than goto (number). But I rather regret allowing it,
because it made writing the optimised version of the interpreter a lot more
difficult.

Switch is a bit slow in a deeply nested loop. For example, when you're
emulating a processor in C, you need to switch on the instruction. That's
often the rate-limiting step in the program. A computed goto can often
prove faster (shift the instruction up four bits, add to the base, jump,
and make sure all your ops are exactly 16 instructions long).
 
B

BartC

glen herrmannsfeldt said:
As far as I know, it started with Fortran I in 1956.

GOTO (10, 20, 30, 40, 50, 60), J

So what's the difference between that, and:

switch (J) {
case 1:
case 2:
....
case 6:
?
I think ALGOL-68 has one, but I am not sure. The description is
in its own language, and not so easy to figure out.

More than likely; you'd just have a row of labels, and perhaps use it
directly as in goto (L1,L2,L3)[J].

But it also has case in... out.
 
B

BartC

case unique:
// do something 3
...
}
}


basically, I can write the above statement completely using
if(flower==rose) goto
if(color==white) goto

type statements.

unfortunately, some of the flowers have strange names such as the ascii
value of '/' or other characters like '%' and so on so switch-case gives
me brevity.

However, inside switch-case I want to jump to certain cases before
breaking to the end.

for example from (rose,pink) I may want to goto unique: . Can I do that by
a

goto unique: ?

Another way to share code between cases is to put it in functions.

So if the code for unique is in dosomething3(), then from rose,pink you just
call dosomething3(). No need for a goto.
 
B

Ben Bacarisse

BartC said:
I think ALGOL-68 has one, but I am not sure. The description is
in its own language, and not so easy to figure out.

More than likely; you'd just have a row of labels, and perhaps use it
directly as in goto (L1,L2,L3)[J].

Not exactly. A label evaluates to a procedure (of mode PROC VOID) so
you can make a row of them, but you have to "call" the procedure, rather
than use goto directly.

[] PROC VOID labels = (L1, L2, L3);
...
labels[j];
But it also has case in... out.

or rather "case in ... out ... esac".
 
P

Paul N

As far as I know, it started with Fortran I in 1956.

GOTO (10, 20, 30, 40, 50, 60), J

Goes to the first statement number if J is 1, the second if J is 2,
and so on. In early Fortran (before 1977) it was undefined if J
was less than 1 or greater than the number of labels. Many as an
extension, and added in Fortran 77, if J is out of range, it goes
to the following statement.

Many BASIC systems implement computed GOTO as

100 ON J GOTO 10, 20, 30, 40, 50, 60

PL/I has LABEL variable arrays, which can either be initialized
with the appropriate labels on the DECLARE, or by specifying an
array element as a statement label. The latter doesn't look so
different from switch/case.

DCL X(5) LABEL INITIAL(ONE, TWO, THREE);

or:

DCL Y(5) LABEL;

then label statements such as:

Y(3): PUT LIST('Three');

Then GOTO X(I); or GOTO Y(J); will go to the appropriate statement.

I think ALGOL-68 has one, but I am not sure. The description is
in its own language, and not so easy to figure out.

As I happen to have a COBOL manual nearby, though haven't actually
written any programs, it seems to have:

GOTO labels DEPENDING ON variable.

In BCPL, labels were numbers just like any other variable. So you could do:

GOTO val -> lab1 , lab2

to choose one of two targets ( -> is the BCPL equivalent of ? : )

or you could use an array; or you could even do

GOTO lab + 4

if jumping to slightly after a label is your idea of fun.
 
K

Kenny McCormack

Paul N said:
In BCPL, labels were numbers just like any other variable. So you could do:

GOTO val -> lab1 , lab2

to choose one of two targets ( -> is the BCPL equivalent of ? : )

or you could use an array; or you could even do

GOTO lab + 4

if jumping to slightly after a label is your idea of fun.

Note, incidentally, that you *can* implement computed goto in C - in fact,
in entirely standard (on topic) C. The details of how to do it escape me
at the moment, but it involves setjmp and longjmp. Basically, you set up
an array of jmpbufs and then longjmp to the one you want. Somebody figured
this out and explained it to me sometime back in the 80s.

Perhaps someone here will take it on as a challenge...
 
B

BartC

Ben Bacarisse said:
BartC said:
I think ALGOL-68 has one, but I am not sure. The description is
in its own language, and not so easy to figure out.

More than likely; you'd just have a row of labels, and perhaps use it
directly as in goto (L1,L2,L3)[J].

Not exactly. A label evaluates to a procedure (of mode PROC VOID) so
you can make a row of them, but you have to "call" the procedure, rather
than use goto directly.

[] PROC VOID labels = (L1, L2, L3);
...
labels[j];

I've just tried it, and you're right. But like this, it's not quite as
succinct. (I base my own syntaxes on A68; with a dynamic language, I can
actually write goto (L1,L2,L3)[J], but will also need goto labels[j] for a
static one. In both cases though I insist on 'goto' to make it clear what
this is.)

But, the fact that A68 treats such a label as a kind of local proc name
gives me an idea for an idea for a language feature that might help the OP
(if it could somehow be implemented today in C).

This is a lightweight call that would pass control to a labelled block
somewhere in this function, just like goto, but then returns at the end of
the block. Access to all local variables is maintained as normal.
Encountering the block also executes it as normal:

rose:
dosomething2();
gosub dosomething3; // use gosub rather than goto or ()
....
unique:
dosomething3:{
.....
}

Well, it's an idea ...
 
J

James Kuyper

Yeah, that's for sure. But just curious -- if one
of those goto's takes execution from outside the
switch's {...} to inside it, will the subsequent
break understand the scope, i.e., where the program
counter should go next? And is that behavior mandated
by standard?

"A break statement terminates execution of the smallest enclosing switch
or iteration statement." (6.8.6.3p2) It doesn't matter how execution of
the program reached the break statement, the only thing that matters is
the location of the break statement.
 
J

JohnF

James Kuyper said:
"A break statement terminates execution of the smallest enclosing switch
or iteration statement." (6.8.6.3p2) It doesn't matter how execution of
the program reached the break statement, the only thing that matters is
the location of the break statement.

Thanks, James. I hadn't been aware of that before.
But after posting, I realized I hadn't exactly asked
the complete question that bothered me. Consider the
following snippet,
char label[100] = "printed during loop";
int nloop = 0;
while ( 1 ) {
int i = 0;
entry_pt:
i++;
printf("%s: i=%d\n",label,i);
if ( i >= 10 ) break;
} /* --- continue --- */
if ( ++nloop < 2 ) {
strcpy(label,"printed after goto");
goto entry_pt; }
Okay, so you know the question: what's the
value of i "printed after goto"? And what's the
general rule about that? And how portable is it?
Thanks,
 
J

James Kuyper

"A break statement terminates execution of the smallest enclosing switch
or iteration statement." (6.8.6.3p2) It doesn't matter how execution of
the program reached the break statement, the only thing that matters is
the location of the break statement.

Thanks, James. I hadn't been aware of that before.
But after posting, I realized I hadn't exactly asked
the complete question that bothered me. Consider the
following snippet,
char label[100] = "printed during loop";
int nloop = 0;
while ( 1 ) {
int i = 0;
entry_pt:
i++;
printf("%s: i=%d\n",label,i);
if ( i >= 10 ) break;
} /* --- continue --- */
if ( ++nloop < 2 ) {
strcpy(label,"printed after goto");
goto entry_pt; }
Okay, so you know the question: what's the
value of i "printed after goto"? And what's the
general rule about that? And how portable is it?
Thanks,

The goto statement enters the block containing the definition of 'i', so
a new instance of i is created with an indeterminate value. The goto
skips the initialization of i, which therefore doesn't occur. At least,
that's how I interpret 6.2.4p6. If the indeterminate value of i is
either a trap representation or INT_MAX, the i++ expression renders the
behavior of the entire program undefined. Otherwise, the value of 'i' is
unspecified, but valid, after the jump. In that case, the increment
occurs normally, and INT_MIN < i && i <= INT_MAX at the time of the
printf() call.

If you want i to have a well-defined value after the goto, move the
label before the declaration of i, or make i static.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,044
Messages
2,570,388
Members
47,052
Latest member
ketan

Latest Threads

Top