do{switch(0)default:{/*break or continue*/;}/*cleanup*/}while(0);

K

Kenny McCormack

Ben Bacarisse said:
argument; almost no one advocates the unbridled use of the goto anymore.

Does anyone advocate the "unbridled" use of *anything*?

That was rhetorical, and the answer is, of course, no. No one would
describe anything they do as "unbridled", so there really is no argument to
win here.

--
Religion is regarded by the common people as true,
by the wise as foolish,
and by the rulers as useful.

(Seneca the Younger, 65 AD)
 
A

Ali

I just came into a case where I could use this:

   do
   {
   // local declarations and initializations
     switch(0)default:
     {
     // bunch of if/else; within that:
     // - "break" performs cleanup;
     // - "continue" skips cleanup.
     /*..*/;
     }
   /*..*/; // cleanup
   }
   while(0);

[Notes: This is 'only' a way to avoid gotos. It places
restrictions on the use of other do/while/for/switch.
The second brace could be before default, but I find
the dummy switch idiom more recognizable that way.]

I'm looking for a classical reference on that construct,
like there is one for
<http://www.lysator.liu.se/c/duffs-device.html>

Or perhaps one for the similar:

   do
   {
   // local declarations and initializations
     switch(condition)
     {
     // leaving is done
     // - "break" performs cleanup;
     // - "continue" skips cleanup.
     case 0:
       /*..*/;
     case 1:
       /*..*/;
       ;
     }
   /*..*/; // cleanup
   }
   while(0);

TIA,

   Francois Grieu


I don't really see a problem with 'goto'. But yes, careless use of
jumps can lead to confusing code paths. If you really want to avoid
'goto' then you just need a function right in the place of 'goto'.


Err = 0;

do
(

switch(condition){
case 1:
Err=funa();
case 2:
Err=funb();
}
if(Err)
CleanUp();

}while(0);


funa()
{

//return non zero for error

return 0;
}

regards,
ali
 
S

Stefan Ram

Ali said:
I don't really see a problem with 'goto'. But yes, careless use of
jumps can lead to confusing code paths. If you really want to avoid
'goto' then you just need a function right in the place of 'goto'.

When functions are small, goto is usually rather harmless.

Real »spaghetti code« can be observed, when the possible
range of a goto can be as large as several 100 lines of code.

When one wants to prove assertions about code, proofs usually
are simpler when control structures are used in a controlled
manner.
 
A

Ali

  When functions are small, goto is usually rather harmless.

  Real »spaghetti code« can be observed, when the possible
  range of a goto can be as large as several 100 lines of code.

  When one wants to prove assertions about code, proofs usually
  are simpler when control structures are used in a controlled
  manner.


'goto' are just harmless (like char *) unless one is campaigning for
fancy "oop" (object oriented programming).

I have no problems with OOP but I do think its just way too artificial
and quite a waste of object code footprint. The folks from oop
community hate good 'goto' and i have no idea why!

regards,
ali
 
F

Francois Grieu

On 2011-07-22 08:49, Francois Grieu wrote:
I just came into a case where I could use this:

do [... convoluted code that looks like "avoid goto at all costs" ...]
while(0);

I must be missing something. Why can't you just do something like this?

cleanup = 0;
[... snip less-convoluted code ...]
I *CAN*. But I'd rather not. I know that most if not all the compilers
I use
will not notice that the "cleanup" variable can be suppressed, and
knowing
that an extra variable exists and code is here to set and test it is
causing
me brain pain. I'd rather use two gotos (or a single goto and a deep
nesting
of ifs, which often will do the job), and get basically the "right"
executable.

If I rationalize: on low-end platforms (PIC..) that I often use, RAM
size is
a few hundred bytes and program space a few kbytes, so every byte counts.

Then I ask you, what's more important, avoiding "goto" or more efficient
code?

There is no general answer. And I don't need one, as my technique
avoids goto without any extra variable. Best of both worlds :)
I repeat my question above.

Same argument.

Francois Grieu
 
W

Willem

Francois Grieu wrote:
) On 2011/22/07 18:24, Kenneth Brody wrote:
)> Then I ask you, what's more important, avoiding "goto" or more efficient
)> code?
)
) There is no general answer. And I don't need one, as my technique
) avoids goto without any extra variable. Best of both worlds :)

Except that your code doesn't avoid "goto", it just writes in a more
convoluted way that avoids the use of the literal string g-o-t-o.

Also, your technique is a lot less clear than just using goto.

So, the advice is to just use goto in this case instead of trying
to adhere to 'never use goto' by the letter but not in spirit.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
G

gwowen

  Real »spaghetti code« can be observed, when the possible
  range of a goto can be as large as several 100 lines of code.

// ...
start_of_loop:
if(condition()) goto end_of_loop;
do_something();
goto start_of_loop;
end_of_loop: return retval;

// ...
while(!condition()) {
do_something();
}
return retval;

I certainly wouldn't argue for the former over the latter, but the
idea that the former is (in some sense) "wrong" . Indeed, there's
every chance that the machine code produced will be identical. One can
write structured code with goto's, but it requires more discipline
than using for(), while(), do(), etc, and becomes harder as function
size increases, because you have to pick unique meaningful label names
for every control structure.
 
K

Keith Thompson

Willem said:
Francois Grieu wrote:
) On 2011/22/07 18:24, Kenneth Brody wrote:
)> Then I ask you, what's more important, avoiding "goto" or more efficient
)> code?
)
) There is no general answer. And I don't need one, as my technique
) avoids goto without any extra variable. Best of both worlds :)

Except that your code doesn't avoid "goto", it just writes in a more
convoluted way that avoids the use of the literal string g-o-t-o.

By that argument, all control structures are really gotos that
don't use the literal string g-o-t-o.

Obviously people differ on how far they're willing to go to avoid
"goto", but there are valid reasons to do so -- otherwise we'd be
using backward gotos instead of loops.

Somebody, I don't remember who it was, argued that the label, not
the "goto" statement", is the real problem. When you see a goto
statement, you know what it does; just look for the correponding
label and you know where the control is going to flow. If you see
a label, you don't easily know how you got there; you have to find
*all* goto statements with that label.

It's not what "disguised gotos" like "break" and "continue" do
that's important, it's what they *don't* do. They don't branch to
arbitrary points in the code, and they don't branch backwards.
Also, your technique is a lot less clear than just using goto.

That's (obviously) a matter of opinion. If it's an accepted idiom
(and I think it is in some circles), then it's perfectly clear.
So, the advice is to just use goto in this case instead of trying
to adhere to 'never use goto' by the letter but not in spirit.

By "the advice", you mean "your advice", right?
 
W

Willem

Keith Thompson wrote:
)> Francois Grieu wrote:
)> ) On 2011/22/07 18:24, Kenneth Brody wrote:
)> )> Then I ask you, what's more important, avoiding "goto" or more efficient
)> )> code?
)> )
)> ) There is no general answer. And I don't need one, as my technique
)> ) avoids goto without any extra variable. Best of both worlds :)
)>
)> Except that your code doesn't avoid "goto", it just writes in a more
)> convoluted way that avoids the use of the literal string g-o-t-o.
)
) By that argument, all control structures are really gotos that
) don't use the literal string g-o-t-o.

I disagree. The technique the OP was using was nothing more than
disguising the goto as a continue or break, and disguising the jump
label as the closing brace on a do or switch block.

See below.

) Obviously people differ on how far they're willing to go to avoid
) "goto", but there are valid reasons to do so -- otherwise we'd be
) using backward gotos instead of loops.

What I'm arguing is that the OP is going way too far to avoid goto.

) Somebody, I don't remember who it was, argued that the label, not
) the "goto" statement", is the real problem. When you see a goto
) statement, you know what it does; just look for the correponding
) label and you know where the control is going to flow. If you see
) a label, you don't easily know how you got there; you have to find
) *all* goto statements with that label.

I agree. And in the case of the technique the OP used, it is even worse.
He is not only using a label, he is using a label that looks like a closing
brace.

) It's not what "disguised gotos" like "break" and "continue" do
) that's important, it's what they *don't* do. They don't branch to
) arbitrary points in the code, and they don't branch backwards.
)
)> Also, your technique is a lot less clear than just using goto.
)
) That's (obviously) a matter of opinion. If it's an accepted idiom
) (and I think it is in some circles), then it's perfectly clear.

I don't think anyone in this group recognized the technique, much less
found it an accepted idiom. This is the first mention of it being so,
and I wonder which circles it would be accepted in.

)> So, the advice is to just use goto in this case instead of trying
)> to adhere to 'never use goto' by the letter but not in spirit.
)
) By "the advice", you mean "your advice", right?

I used 'the advice' because others in this thread have been giving
the same advice, and therefore 'my advice' would be incorrect.

Apparently you take issue with this usage, but you don't explain why.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
K

Keith Thompson

Willem said:
Keith Thompson wrote:
)> Francois Grieu wrote:
)> ) On 2011/22/07 18:24, Kenneth Brody wrote:
)> )> Then I ask you, what's more important, avoiding "goto" or more efficient
)> )> code?
)> )
)> ) There is no general answer. And I don't need one, as my technique
)> ) avoids goto without any extra variable. Best of both worlds :)
)>
)> Except that your code doesn't avoid "goto", it just writes in a more
)> convoluted way that avoids the use of the literal string g-o-t-o.
)
) By that argument, all control structures are really gotos that
) don't use the literal string g-o-t-o.

I disagree. The technique the OP was using was nothing more than
disguising the goto as a continue or break, and disguising the jump
label as the closing brace on a do or switch block.

See below.

The OP was emulating a feature that the language doesn't support
directly: defining an arbitrary block of code with a simple command
to bail out of it at any point.

C has built-in statements to terminate the execution of a loop
or of a switch statement. It has no such statements for blocks.
The "do ... while (0)" trick is a way of emulating this nonexistent
statement. I'm not saying it's not a bit ugly, or even that I'd
use it myself, but I can see the logic of it.
) Obviously people differ on how far they're willing to go to avoid
) "goto", but there are valid reasons to do so -- otherwise we'd be
) using backward gotos instead of loops.

What I'm arguing is that the OP is going way too far to avoid goto.

Which is a perfectly valid opinion. I'm not even sure I disagree.
) Somebody, I don't remember who it was, argued that the label, not
) the "goto" statement", is the real problem. When you see a goto
) statement, you know what it does; just look for the correponding
) label and you know where the control is going to flow. If you see
) a label, you don't easily know how you got there; you have to find
) *all* goto statements with that label.

I agree. And in the case of the technique the OP used, it is even worse.
He is not only using a label, he is using a label that looks like a closing
brace.

That's one way of looking at it. Another is that he's creating
a well-defined lexical scope and using "break" or "continue" to
terminate execution of code in that scope. We do the same thing
for loops; why not for simple blocks?
) It's not what "disguised gotos" like "break" and "continue" do
) that's important, it's what they *don't* do. They don't branch to
) arbitrary points in the code, and they don't branch backwards.
)
)> Also, your technique is a lot less clear than just using goto.
)
) That's (obviously) a matter of opinion. If it's an accepted idiom
) (and I think it is in some circles), then it's perfectly clear.

I don't think anyone in this group recognized the technique, much less
found it an accepted idiom. This is the first mention of it being so,
and I wonder which circles it would be accepted in.

I've seen it in existing code. I'm probably not at liberty to say
where. Sorry.
)> So, the advice is to just use goto in this case instead of trying
)> to adhere to 'never use goto' by the letter but not in spirit.
)
) By "the advice", you mean "your advice", right?

I used 'the advice' because others in this thread have been giving
the same advice, and therefore 'my advice' would be incorrect.

Apparently you take issue with this usage, but you don't explain why.

Perhaps "our advice" would have been better? Not a big deal.
 
J

Jens Schweikhardt

in <[email protected]>:
# On 7/23/2011 9:06 AM, Jens Schweikhardt wrote:
#> in<[email protected]>:
#> ....
#> # Yes, this is wrong. But I think only 1/3 wrong.
#>
#> The discovery of the truth quark! :)
#
# So, truths are really either 2/3 right, or 1/3 wrong?

Two wrongs cancel a right, that's for sure. I've lost my copy of QLD
(Quantumlogodynamics).

Regards,

Jens
 
N

Nick Keighley

lawn-mowing or madrigal singing?


at the expense of really ugly and obscure code...
By that argument, all control structures are really gotos that
don't use the literal string g-o-t-o.

Obviously people differ on how far they're willing to go to avoid
"goto", but there are valid reasons to do so -- otherwise we'd be
using backward gotos instead of loops.

Somebody, I don't remember who it was, argued that the label, not
the "goto" statement", is the real problem.  When you see a goto
statement, you know what it does; just look for the correponding
label and you know where the control is going to flow.  If you see
a label, you don't easily know how you got there; you have to find
*all* goto statements with that label.

It's not what "disguised gotos" like "break" and "continue" do
that's important, it's what they *don't* do.  They don't branch to
arbitrary points in the code, and they don't branch backwards.

it wasn't just the backwards jumps that were the problem. It was the
tangle's

For instance this is reasonably clear:-

loop:
if (!finished)
{
do_more_stuff();
goto loop;
}

This less so

loop1:
if (!finished)
{
do_first_stuff();
if (reloop())
goto loop1;
loop2:
do_second_stuff();
if (sudden_death())
goto end;
do_third_stuff()
goto loop1;
}

end:
skip_many_pages();
if (reprocess_event())
goto loop2;

The full horror is jumping into a loop. A simple loop can be recoded
as a for or while. the second example needs a lot more analysis. The
above is much *more* structured than the typical code-de-jour. There
could be a dozen pages between the top and bottom of (maybe) a loop.
And those dozen pages whould be nested ten deep (unless the coder
thought indentation was for wimps).

When gotos are discussed people don't always realise the full horror
of old code.

That's (obviously) a matter of opinion.  If it's an accepted idiom
(and I think it is in some circles), then it's perfectly clear.

glad I'm not in those circles!


<snip>
 
N

Nick Keighley

'goto' are just harmless (like char *) unless one is campaigning for
fancy "oop" (object oriented programming).

I fail to see the connection
I have no problems with OOP but I do think its just way too artificial
and quite a waste of object code footprint.

strong encapsulation seems a fairly unalloyed good to me. And that
seems a good chunk of OOP's appeal. said:
 The folks from oop
community hate good 'goto' and i have no idea why!

dislike of goto long preceeds OO in mainstream programming. Look up
"Structured Programming", "Dijkstra", "Software Crisis". What do they
teach kids today?
 
F

Francois Grieu

The OP was emulating a feature that the language doesn't support
directly: defining an arbitrary block of code with a simple command
to bail out of it at any point.

C has built-in statements to terminate the execution of a loop
or of a switch statement. It has no such statements for blocks.
The "do ... while (0)" trick is a way of emulating this nonexistent
statement. I'm not saying it's not a bit ugly, or even that I'd
use it myself, but I can see the logic of it.


I'm the OP, and I second Keith's nice wording of the intend.
This is an idiom to cleanly leave the appropriate of two nested
blocks.

It is often necessary, and the alternatives are
- goto + label;
- an extra variable determining if the code between the end of
the two blocks shall be executed;
- duplicating the code between the end of the two blocks.

I think code duplication should be ruled out in most cases, for
maintainability reasons (as for object code compactness, many
compilers are good at catching that).

I viscerally hate extra variables, for their typical impact on code
size and in some occasions on speed; and because my ability to grasp
the working of a code section reduces quickly with the number of
variables. They eat scarce space in my short-term code-grasping memory.

To a lesser degree, a label's name has the same effect. And more
importantly it raise fear that some other code not immediately
visible could reach the label and invalidate my understanding of
the code's working.

Another benefit of not having a label is that it solves the issue of
the label's name. This is a benefit if the construct is reused,
especially in the same function, and for generated code (macro, or
use of C as an intermediary language).


Francois Grieu
 
N

Nick Keighley

"Nick Keighley" <[email protected]> ha scritto nel messaggio

For instance this is reasonably clear:-

loop:
   if (!finished)
   {
       do_more_stuff();
       goto loop;
   }

This less so

loop1:
   if (!finished)
   {
       do_first_stuff();
       if (reloop())
           goto loop1;
loop2:
       do_second_stuff();
       if (sudden_death())
           goto end;
       do_third_stuff()
       goto loop1;
    }

end:
    skip_many_pages();
    if (reprocess_event())
        goto loop2;

#i not have all your fears
#this "goto loop2;" seem to me a problem [i never wrote something as that]

trust me I've seen stuff like this. If you restrict your gotos to
structures isomorphic to structured programs then they aren't too hard
to analyse. But they *do* need to be analysed and this is why a goto-
ful program is harder than a goto-less program (everything else being
equal!)

#i there will write

# {renewVaribleLoop1and2(); goto loop1}
#or but with some problem
# {renewVaribleLoop1and2(); goto loop2}

#and write a end condition that exit function
#or program

I don't know how you can be sure the two programs are equivalent.
Which is my point.

#but i woudl write it in this way
----------
loop1:
          if(finished)  goto end;
          do_first_stuff();
          if (reloop()) goto loop1;
loop2:
       do_second_stuff();
       if(sudden_death()) goto   end;
       do_third_stuff()   goto loop1;
end:
...
finished=0;
...
goto loop1;
or
{inizilizesudden_death(); goto loop2}
---------

I refer the honourable memeber to my response to his previous
question.


The full horror is jumping into a loop.

#yes, if one excluse the case the loop start in the middle as
#     i=0; goto  .b;
# .a: printf("%d\n", i);
#     ++i;
# .b: if(i<=someVar) goto .a;

A simple loop can be recoded
as a for or while. the second example needs a lot more analysis. The
above is much *more* structured than the typical code-de-jour. There
could be a dozen pages between the top and bottom of (maybe) a loop.
And those dozen pages whould be nested ten deep (unless the coder
thought indentation was for wimps).

When gotos are discussed people don't always realise the full horror
of old code.

#olds not used indentation and multi instruction for line with goto
#for reduce size of function and see all function
#with the right indentation...

trust twelve page functions don't squish down onto one page no matter
how many statements you put on a line. The great advantage of gotos is
taht you dispense with the indentation. Hence enabling you to compress
the code even more.


loop1: if (!finished) goto end
do_first_stuff();
if (reloop())goto loop1;
loop2: do_second_stuff();
if (sudden_death()) goto end;
do_third_stuff()
goto loop1;
end: skip_many_pages();
if (reprocess_event()) goto loop2;
 
H

Hallvard B Furuseth

To my mind this is too clever and loses as much in clarity as avoiding
goto/label gains. For a block/exit construct it overloads continue and
break arbitrarily: If you'd merely said you had a block construct where
continue and break exit with/without cleanup, I'd expect "continue" to
be the soft exit with cleanup, "break" to be the hard one without.

OTOH I've sometimes written

switch (0) default: {
... if (...) break; ...
}

but I don't mind a few labels instead, with clear purposes like 'done:'
and 'abort:'. With lots of jumps due to error checking, I tend to
structure C code as it would be without error checking, and then put the
error handling label(s) at the end. Just avoid gotos when convenient
and keep the remaining ones readable. E.g. don't goto both up and down
in the same function, which makes it hard to see if there is a hidden
loop. Labels in the middle of a function make program flow harder to
see than those near the beginning/end. Except an occasional end_loop:.
I *CAN*. But I'd rather not. I know that most if not all the compilers I
use will not notice that the "cleanup" variable can be suppressed,

Have you looked at the assembly output to check this? You might be
right if you were talking about code like this:

int f(int a) {
int c = 0;
if (a < 0) {
c = 1;
a *= a;
}
g();
if (c) {
h();
}
return a;
}

because c might be either set or reset after executing g(). But actually
gcc -Os (optimize for space) handles even that fine, and treats it as

int f(int a) {
if (a < 0) {
a *= a;
g();
h();
} else
g();
return a;
}
and
knowing that an extra variable exists and code is here to set and test
it is causing me brain pain. I'd rather use two gotos (or a single goto
and a deep nesting of ifs, which often will do the job), and get
basically the "right" executable.

Up to here, this sounds like the itch for premature optimization. In
those cases, just Get Over It. Really.
If I rationalize: on low-end platforms (PIC..) that I often use, RAM
size is a few hundred bytes and program space a few kbytes, so every
byte counts. Even on relatively powerful CPUs (Arm, x86) and when memory
is not an issue, using one more register may force the shift of
something into memory rather than in a register, or/and a little extra
code could abruptly reduce cache efficiency, and in turn slow down
things considerably. I bet I could construct an articial demo where the
suggested change increases execution time/power draw quite perceptibly,
say by 30%.

OK, that makes sense.

However, when you do decide to help the compiler, take care to check
that it actually was helpful or at least that it did no harm. Probably
not a problem in his case, but it's not unusual for such "help" to be a
pessimization, if the code becomes harder to analyze for the compiler
than more natural code would be. A classic example is code which walks
an array, a common operation which good compilers recognize and have
lots of tricks to deal with. But if you instead helpfully start doing
pointer arithmetic on the array base/end, the compiler may give up
on trying those tricks and instead just compile your code step by step.
 
F

Francois Grieu

To my mind this is too clever and loses as much in clarity as avoiding
goto/label gains. For a block/exit construct it overloads continue and
break arbitrarily: If you'd merely said you had a block construct where
continue and break exit with/without cleanup, I'd expect "continue" to
be the soft exit with cleanup, "break" to be the hard one without.

OTOH I've sometimes written

switch (0) default: {
... if (...) break; ...
}

but I don't mind a few labels instead, with clear purposes like 'done:'
and 'abort:'. With lots of jumps due to error checking, I tend to
structure C code as it would be without error checking, and then put the
error handling label(s) at the end. Just avoid gotos when convenient
and keep the remaining ones readable. E.g. don't goto both up and down
in the same function, which makes it hard to see if there is a hidden
loop. Labels in the middle of a function make program flow harder to
see than those near the beginning/end. Except an occasional end_loop:.


Have you looked at the assembly output to check this?

Yes, repeatedly on PIC18, 8051, ST7, ST7M; and recently on ARM,
though not with all optimizations, since they break the
vendor-supplied code frameword :-(
Not with x86/Amd64 compilers since Turbo C. I take your word
that gcc knows that trick. My "most if not all" was to account
for gcc, LLVM, and other leading edge compilers.

Francois Grieu
 
H

Hallvard B Furuseth

Francois Grieu said:
Yes, repeatedly on PIC18, 8051, ST7, ST7M; and recently on ARM,
though not with all optimizations, since they break the
vendor-supplied code frameword :-(

Oh, yuck. gcc without optimization also keeps the cleanup variable.
 

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

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top