Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

regarding "goto" in C

48 views
Skip to first unread message

M.B

unread,
Jan 4, 2006, 12:29:12 AM1/4/06
to
Guys,
Need some of your opinion on an oft beaten track
We have an option of using "goto" in C language, but most testbooks
(even K&R) advice against use of it.
My personal experience was that goto sometimes makes program some more
cleaner and easy to understand and also quite useful (in error handling
cases).
So why goto is outlawed from civilized c programmers community.

is there any technical inefficiency in that.

Thank you

Thad Smith

unread,
Jan 4, 2006, 1:29:07 AM1/4/06
to
M.B wrote:

> Need some of your opinion on an oft beaten track
> We have an option of using "goto" in C language, but most testbooks
> (even K&R) advice against use of it.
> My personal experience was that goto sometimes makes program some more
> cleaner and easy to understand and also quite useful (in error handling
> cases).
> So why goto is outlawed from civilized c programmers community.

About 1968 or so Edsger Dijkstra wrote an article, published as a Letter
to the Editor in the ACM Communications magazine, titled Go To
Considered Harmful. He observed that unrestrained use of goto--what we
now refer to as "spaghetti code"--makes a program hard to understand and
therefore often has bugs. Shortly afterwards, there was much activity
to develop a method of programming, called structured programming, that
decomposed code into neat blocks, such as iteration, sequence, and
selection, such that no gotos were needed! It caught on as a way to
organize code.

The reason it is still with us is that as a general rule is that it
still helps to prevent the spaghetti code mess. Does it always produce
more understandable code? I don't think so, although it usually comes
close. In my opinion, it is a rule that should be understood and used
well before attempting to break it.

> is there any technical inefficiency in that.

In general, there is some inefficiency with the elimination of goto.
In order to eliminate goto, you often have to implement additional
variables or flags to carry information from an inner loop to the
outside in order to stop intermediate processing, which is not needed if
you simply jump directly out of a loop. Also, there tends to be some
code duplication. Some people, such as I, cheat by returning from a
function more than one place in the body, a violation of the strict
structured approach.

At the machine level, there is almost always a jump or branch
instruction that performs a goto function.

--
Thad

Keith Thompson

unread,
Jan 4, 2006, 1:41:17 AM1/4/06
to
"M.B" <mbpr...@gmail.com> writes:
> Need some of your opinion on an oft beaten track
> We have an option of using "goto" in C language, but most testbooks
> (even K&R) advice against use of it.
> My personal experience was that goto sometimes makes program some more
> cleaner and easy to understand and also quite useful (in error handling
> cases).
> So why goto is outlawed from civilized c programmers community.

It's not "outlawed" unless you're working with a coding standard that
forbids it.

Goto statements can easily lead to "spaghetti code". The real problem
isn't the goto statement itself; it's the label. Whenever you see a
label in code, it's very difficult to tell how the program could have
gotten there. So-called "structured programming" intstead builds a
program structure from a set of higher-level constructs, such as
if/then/else, loops, switches, and so forth.

A program's structure often corresponds to something in the real-world
entity being modeled. An if statement corresponds to a decision. A
loop corresponds to doing something repeatedly. A goto statement
corresponds to ... well, to jumping from one point in the program to
another; it rarely matches anything in the real world (unless the
program is modeling a finite state machine).

Used with care, however, they can be useful, especially as a
substitute for a control structure that's missing from the language.
C doesn't have an exception handling mechanism, so gotos can be useful
for error handling (bailing out of a nested construct when something
goes wrong). C doesn't have a multi-level break statement, so gotos
can be useful for that.

A goto statement that branches backward, or that does something that
could have been done straightforwardly with a loop, is almost always a
bad idea.

The classic essay on the topic, from 1968, is Edsger W. Dijkstra's
"Go To Statement Considered Harmful", available at
<http://www.acm.org/classics/oct95/>.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

"Nils O. Selåsdal"

unread,
Jan 4, 2006, 3:52:55 AM1/4/06
to
Keith Thompson wrote:
> The classic essay on the topic, from 1968, is Edsger W. Dijkstra's
> "Go To Statement Considered Harmful", available at
> <http://www.acm.org/classics/oct95/>.
>
Let's not forget
"Structured Programming with go to Statements"
http://portal.acm.org/citation.cfm?id=356640


tmp123

unread,
Jan 4, 2006, 4:12:41 AM1/4/06
to
M.B wrote:
> My personal experience was that goto sometimes makes program some more
> cleaner and easy to understand and also quite useful (in error handling
> cases).

Hi,

What you say has been experienced also by lots of programmers. Error
handling is sometimes easier to do with "goto".

We could say (saving a lot of details) that in order to skip the
contradiction
between "goto's are bad" and "goto's are good for error handling", the
concept of "exceptions" has been created.

Thus, I suggest you to review the usage of "try"/"catch"/... (forget my
sugestion if you know them).

Kind regards.

Richard Heathfield

unread,
Jan 4, 2006, 4:21:26 AM1/4/06
to
tmp123 said:

> Thus, I suggest you to review the usage of "try"/"catch"/... (forget my
> sugestion if you know them).

They don't exist in C.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

tmp123

unread,
Jan 4, 2006, 4:36:26 AM1/4/06
to

Richard Heathfield wrote:
> tmp123 said:
>
> > Thus, I suggest you to review the usage of "try"/"catch"/... (forget my
> > sugestion if you know them).
>
> They don't exist in C.


Yes, you have reason, I forget to remark it (a good reason to start in
C++).

However, I'm sure you known it is posible a workaround with a few
macros like:

#define TRY if(...(setjmp(...
#define CATCH else
#define RAISE logjmp(...

Kind regards.

Richard Heathfield

unread,
Jan 4, 2006, 4:43:33 AM1/4/06
to
tmp123 said:

>
> Richard Heathfield wrote:
>> tmp123 said:
>>
>> > Thus, I suggest you to review the usage of "try"/"catch"/... (forget my
>> > sugestion if you know them).
>>
>> They don't exist in C.
>
>
> Yes, you have reason, I forget to remark it (a good reason to start in
> C++).

No, it's not. It is a good thing to know how to write C++ programs, and also
a good thing to know how to write C programs, and it is an excellent thing
to know when to use which.

> However, I'm sure you known it is posible a workaround with a few
> macros like:
>
> #define TRY if(...(setjmp(...
> #define CATCH else
> #define RAISE logjmp(...

I really wouldn't do that if I were you. There are subtleties to the
portable use of setjmp/longjmp which make it a non-trivial exercise.

Chuck F.

unread,
Jan 4, 2006, 6:04:35 AM1/4/06
to
Keith Thompson wrote:
>
... snip ...

>
> A goto statement that branches backward, or that does something
> that could have been done straightforwardly with a loop, is
> almost always a bad idea.
>
> The classic essay on the topic, from 1968, is Edsger W.
> Dijkstra's "Go To Statement Considered Harmful", available at
> <http://www.acm.org/classics/oct95/>.
>

See also:

<http://pplab.snu.ac.kr/courses/adv_p104/papers/p261-knuth.pdf>

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>

Chuck F.

unread,
Jan 4, 2006, 6:07:54 AM1/4/06
to
tmp123 wrote:
> M.B wrote:
>
>> My personal experience was that goto sometimes makes program
>> some more cleaner and easy to understand and also quite useful
>> (in error handling cases).
>
> What you say has been experienced also by lots of programmers.
> Error handling is sometimes easier to do with "goto".
>
> We could say (saving a lot of details) that in order to skip the
> contradiction between "goto's are bad" and "goto's are good for
> error handling", the concept of "exceptions" has been created.
>
> Thus, I suggest you to review the usage of "try"/"catch"/...
> (forget my sugestion if you know them).

You have done a naughty thing. There is no "try/catch" in the C
language, thus they are not applicable here. In fact they are
off-topic. You might have been thinking of some other language
with a vague resemblance to C.

John Bode

unread,
Jan 4, 2006, 10:51:08 AM1/4/06
to

M.B wrote:
> Guys,
> Need some of your opinion on an oft beaten track
> We have an option of using "goto" in C language, but most testbooks
> (even K&R) advice against use of it.
> My personal experience was that goto sometimes makes program some more
> cleaner and easy to understand and also quite useful (in error handling
> cases).
> So why goto is outlawed from civilized c programmers community.
>

IME, there are cases where a goto is useful, but they are few and far
between. I have no problems with gotos provided some basic rules are
followed:

1. Branch forward only.
2. Never branch into the middle of another control structure (if, for,
while, etc.)
3. Don't use goto if another control structure can do the same job.

> is there any technical inefficiency in that.

ISTR some verbiage in H&S that the presence of a goto can hinder some
compiler optimizations.

Chuck F.

unread,
Jan 4, 2006, 12:06:25 PM1/4/06
to
John Bode wrote:
>
... snip ...

>
> IME, there are cases where a goto is useful, but they are few and far
> between. I have no problems with gotos provided some basic rules are
> followed:
>
> 1. Branch forward only.

Counterexample:

preliminarysetup();
outer: while (condition1) {
dosumthing();
while (condition2) {
dosumthingelse();
if (condition3) goto outer;
domore();
}
dostillmore();
}

The goto cannot be replaced by break or continue, and even if it
could the goto is clearer.

> 2. Never branch into the middle of another control structure
> (if, for, while, etc.)

See the Knuth paper (reference from me upthread) for a
counterexample. s/Never/Almost never/

> 3. Don't use goto if another control structure can do the same
> job.

This one I can accept.

Eric Sosman

unread,
Jan 4, 2006, 12:46:47 PM1/4/06
to
Chuck F. wrote:

> John Bode wrote:
>
>>
> ... snip ...
>
>>
>> IME, there are cases where a goto is useful, but they are few and far
>> between. I have no problems with gotos provided some basic rules are
>> followed:
>>
>> 1. Branch forward only.
>
>
> Counterexample:
>
> preliminarysetup();
> outer: while (condition1) {
> dosumthing();
> while (condition2) {
> dosumthingelse();
> if (condition3) goto outer;
> domore();
> }
> dostillmore();
> }
>
> The goto cannot be replaced by break or continue, and even if it could
> the goto is clearer.

Note that this can be trivially converted to a forward
branch by writing `outer: ;' just before the closing brace
of the outer loop. Note, too, that this conversion would be
necessary, not just possible, if the outer loop were a `for'
or a `do...while'.

--
Eric Sosman
eso...@acm-dot-org.invalid

Richard Tobin

unread,
Jan 4, 2006, 1:13:37 PM1/4/06
to
In article <1136389868....@o13g2000cwo.googlegroups.com>,
John Bode <john...@my-deja.com> wrote:
>1. Branch forward only.

Branching backwards to simulate tail-recursion seems unobjectionable.

-- Richard

Red Cent

unread,
Jan 4, 2006, 1:31:49 PM1/4/06
to
Two things I think need pointed out here.

1) As mentioned earlier in this thread, goto does NOT necessarily lead
to poor programming. If used with care, goto maybe a good choice, but
there is always an alternative. Whether it's a function call, a case
switch. All of these can be good alternatives BUT they can be abused
as well.

At least with a function call you know where and when that piece of
code will execute. But with labelled lines for goto purposes, it's
difficult to tell when it's being called, and when those lines just run
because of the order of execution.

2) Today's goto? #define!

I have often seen (and not just in purposely obfuscated code)
ridiculous define statements due to laziness. These problems often
disappear once people begin working together in a group, or review each
other's source code.

Keith Thompson

unread,
Jan 4, 2006, 1:37:21 PM1/4/06
to
"John Bode" <john...@my-deja.com> writes:
[...]

> IME, there are cases where a goto is useful, but they are few and far
> between. I have no problems with gotos provided some basic rules are
> followed:
>
> 1. Branch forward only.
> 2. Never branch into the middle of another control structure (if, for,
> while, etc.)
> 3. Don't use goto if another control structure can do the same job.

Your rule 3 would eliminate goto statements altogether. There's a
well known theorem that any program using gotos can be transformed
into an equivalent program using only a particular small set of
structured control constructs (possibly with some extra flag
variables).

I'd amend your rule 3 to

3. Use goto only if it's (significantly) cleaner than any of the
equivalent alternatives.

and add:

4. If forced by circumstances to use a goto, curse under my breath
about the lack of a cleaner alternative in the language.

I can think of 3 cases where a goto is justified in C: an explicit
finite state machine, where a goto actually models something in the
problem domain (this could also be implemented as a switch statement
in a loop with an explicit state variable); error handling (due to the
lack of a decent exception handling mechanism); and breaking out of a
nested loop (due to C's regrettable lack of multi-level break).

The latter two could also be implemented by wrapping part of the code
in a small (perhaps inline) function, and using a return statement to
break out of it, but that's not necessarily an improvement. In
particular, it causes problems if an inner loop accesses variables
declared in outer scopes.

Marco

unread,
Jan 4, 2006, 1:40:30 PM1/4/06
to

M.B wrote:
> So why goto is outlawed from civilized c programmers community.

several coding standard/style books

"Enough Rope to Shoot Yourself In the Foot"
" The Elements of C Programming Style"

suggest that a forward goto from nested loops is perfectly acceptable

they have examples similar to

while( condtion1 )
{
while( condtion2 )
{
if (something_bad)
goto leave;
...
}
}
leave:
...

I have used this in practice once or twice.

Chuck F.

unread,
Jan 4, 2006, 2:24:46 PM1/4/06
to

I submit that coding a jump forward to execute a jump backward is
code obfuscation. As further evidence I cite the need for the
extraneous semicolon in this case.

For the do-while I agree, but with a for-loop I also claim that the
wrong loop is in use. I generally do not approve of using the for
as a generic loop construct when other constructs have the same effect.

Keith Thompson

unread,
Jan 4, 2006, 2:36:07 PM1/4/06
to

C has perfectly good looping constructs.

August Karlstrom

unread,
Jan 4, 2006, 4:22:55 PM1/4/06
to
Keith Thompson wrote:
[snip]

> I can think of 3 cases where a goto is justified in C: an explicit
> finite state machine, where a goto actually models something in the
> problem domain (this could also be implemented as a switch statement
> in a loop with an explicit state variable); error handling (due to the
> lack of a decent exception handling mechanism); and breaking out of a
> nested loop (due to C's regrettable lack of multi-level break).
>
> The latter two could also be implemented by wrapping part of the code
> in a small (perhaps inline) function, and using a return statement to
> break out of it, but that's not necessarily an improvement. In
> particular, it causes problems if an inner loop accesses variables
> declared in outer scopes.

That's because C doesn't support local subroutines. If your language
does, it's a neat solution.


August

--
I am the "ILOVEGNU" signature virus. Just copy me to your
signature. This email was infected under the terms of the GNU
General Public License.

Richard Tobin

unread,
Jan 4, 2006, 5:50:29 PM1/4/06
to
In article <lnu0cj9...@nuthaus.mib.org>,

Keith Thompson <ks...@mib.org> wrote:
>> Branching backwards to simulate tail-recursion seems unobjectionable.
>
>C has perfectly good looping constructs.

C has perfectly good recursion, but not all compilers implement it
well enough for some purposes.

I would usually rather overcome the deficiencies of compilers by using
a goto than by changing the algorithm.

-- Richard

Emmanuel Delahaye

unread,
Jan 4, 2006, 5:55:47 PM1/4/06
to
M.B a écrit :

> We have an option of using "goto" in C language, but most testbooks
> (even K&R) advice against use of it.

A good advice, specially targetted to beginners.

> My personal experience was that goto sometimes makes program some more
> cleaner and easy to understand and also quite useful (in error handling
> cases).

True enough.

> So why goto is outlawed from civilized c programmers community.

I think goto is for experienced programmers who know the limits and
dangers induced by the use of this very sharp tool...

> is there any technical inefficiency in that.

No. It's essentially a design issue. Noone like spaghetti code.

--
A+

Emmanuel Delahaye

pemo

unread,
Jan 4, 2006, 6:00:19 PM1/4/06
to

"Richard Tobin" <ric...@cogsci.ed.ac.uk> wrote in message
news:dphjfl$8iu$1...@pc-news.cogsci.ed.ac.uk...

> C has perfectly good recursion, but not all compilers implement it
> well enough for some purposes.

'but not all compilers implement it well enough for some purposes'

Please give an explanation

[I'm freaked out, and cannot sleep now]


Emmanuel Delahaye

unread,
Jan 4, 2006, 6:00:48 PM1/4/06
to
Nils O. Selåsdal a écrit :

> "Structured Programming with go to Statements"

This was my favorite game when I was programming in BASIC (the true one,
with "10 GOTO hell" etc.) and Assembly language... It drove by teacher
and supervisor crazy !

--
A+

Emmanuel Delahaye

Malcolm

unread,
Jan 4, 2006, 6:01:15 PM1/4/06
to

"Keith Thompson" <ks...@mib.org> wrote

> I can think of 3 cases where a goto is justified in C: an explicit
> finite state machine, where a goto actually models something in the
> problem domain (this could also be implemented as a switch statement
> in a loop with an explicit state variable); error handling (due to the
> lack of a decent exception handling mechanism); and breaking out of a
> nested loop (due to C's regrettable lack of multi-level break).
>
I'd add a fourth - occasionally scratch code to examine program flow might
need a goto
(You can implement the debug control structure with loops, but that might
entail messy brackets that obscure the real non-debug control structure.)


Richard Tobin

unread,
Jan 4, 2006, 6:16:51 PM1/4/06
to
In article <dphk24$i27$1...@news.ox.ac.uk>, pemo <usenet...@gmail.com> wrote:

>> C has perfectly good recursion, but not all compilers implement it
>> well enough for some purposes.
>
>'but not all compilers implement it well enough for some purposes'
>
>Please give an explanation

Consider a function of the form

some_type foo(some args)
{
...
if(some condition)
return foo(some other args);
...
}

(obviously the recursive call has to be in a conditional). The
compiler does not need to create a new stack frame for the recursive
call, since it will never return to the current frame (except to
return immediately). This is called "tail-recursion optimization",
and if you can rely on it then you can use recursion of this sort even
in cases where the depth of recursion would be very deep, and might
otherwise run out of memory.

Some C compilers do this optimization in some cases (gcc for example)
but it is not guaranteed by the standard. Some other languages
(notably Scheme) do guarantee it.

-- Richard

Christian Bau

unread,
Jan 4, 2006, 8:20:45 PM1/4/06
to
In article <1136399508.9...@g14g2000cwa.googlegroups.com>,
"Red Cent" <truthg...@sbcglobal.net> wrote:

> Two things I think need pointed out here.
>
> 1) As mentioned earlier in this thread, goto does NOT necessarily lead
> to poor programming. If used with care, goto maybe a good choice, but
> there is always an alternative. Whether it's a function call, a case
> switch. All of these can be good alternatives BUT they can be abused
> as well.

All these anti-goto tirades come from a time in ancient history, where
widespread programming language had nothing but goto to implement simple
control flow. For example, in Fortran 66 there was not even a simple if
/ else / endif available. The forced use of goto because alternatives
were not available did certainly make programs less readable.

If anyone is studying C today, it is hard to imagine why they would use
goto in a substantial number of places, unless there is an especially
warped mind in place. If/else, loops, break and continue are just so
much easier to use in most cases.

Peter Nilsson

unread,
Jan 4, 2006, 9:09:52 PM1/4/06
to

Indeed. The only caveat here is that labels like 'leave' must label
actual statements.
If there isn't one, e.g. if you're jumping into the end of a block, you
should create
an empty statement...

void foo(void)
{
while (cond1)
{
while (cond2)
{
while (cond3)
{
if (cond4) goto continue_while_1;
...
}
}
continue_while_1:
; /* ; (or equivalent) needed */
}
}

--
Peter

Richard Bos

unread,
Jan 5, 2006, 4:03:38 AM1/5/06
to
Thad Smith <Thad...@acm.org> wrote:

> M.B wrote:
>
> > So why goto is outlawed from civilized c programmers community.
>

> About 1968 or so Edsger Dijkstra wrote an article, published as a Letter
> to the Editor in the ACM Communications magazine, titled Go To
> Considered Harmful.

Actually, he didn't. When he wrote it, it was titled differently. Editor
of the ACM Considered Harmful.

Richard

Michael Wojcik

unread,
Jan 6, 2006, 12:02:31 PM1/6/06
to

In article <christian.bau-CD6...@slb-newsm1.svr.pol.co.uk>, Christian Bau <christ...@cbau.freeserve.co.uk> writes:
>
> If anyone is studying C today, it is hard to imagine why they would use
> goto in a substantial number of places, unless there is an especially
> warped mind in place.

Is it really? A number of regulars here seem to have imagined it,
but perhaps we are particularly imaginative, or particularly warped.

I have a large code base where at least one goto appears in the
majority of the functions. They're all for handling errors with a
single point of return, but they definitely occupy "a substantial
number of places" in the code.

Now, that style may not be to your preference, but I submit that it's
hardly difficult to imagine why someone might employ it.

--
Michael Wojcik michael...@microfocus.com

When [Columbus] landed on America it was more like an evasion than a
discovery. -- Matt Walsh

Herbert Rosenau

unread,
Jan 6, 2006, 1:49:49 PM1/6/06
to
On Wed, 4 Jan 2006 15:51:08 UTC, "John Bode" <john...@my-deja.com>
wrote:

> IME, there are cases where a goto is useful, but they are few and far
> between.

Please name one! Only one. In 25 years of programming in C i have
never found a single one. I've written small, middle and really big
applications, I've written drivers, whole OSes for realtime
environments but have never found a reason to write goto.

> I have no problems with gotos provided some basic rules are
> followed:
>
> 1. Branch forward only.
> 2. Never branch into the middle of another control structure (if, for,
> while, etc.)
> 3. Don't use goto if another control structure can do the same job.
>
> > is there any technical inefficiency in that.
>
> ISTR some verbiage in H&S that the presence of a goto can hinder some
> compiler optimizations.

In all of the 25 years I had to write code in highest security and
time critical environments whereasd any fault would have cost human
live.

There were only 3 rules to follow:
1. readability
not necessary for beginners in C but experts
2. security
avoid any obsurity
3. maintenacaiblity

All 3 rules contains avoiding goto by design, not code. Giving the
code a chance for goto is violating at least one of the 3 rules,
therefore a cause to redesign the sequence.


--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2 Deutsch ist da!

Herbert Rosenau

unread,
Jan 6, 2006, 1:49:50 PM1/6/06
to
On Wed, 4 Jan 2006 17:06:25 UTC, "Chuck F. " <cbfal...@yahoo.com>
wrote:

> John Bode wrote:
> >
> ... snip ...
> >
> > IME, there are cases where a goto is useful, but they are few and far
> > between. I have no problems with gotos provided some basic rules are
> > followed:
> >
> > 1. Branch forward only.
>

> Counterexample:
>
> preliminarysetup();
> outer: while (condition1) {
> dosumthing();
> while (condition2) {
> dosumthingelse();
> if (condition3) goto outer;

Very bad design!

> domore();
> }
> dostillmore();
> }
>
> The goto cannot be replaced by break or continue, and even if it
> could the goto is clearer.

Redesign the whole block and you will avoid the label and the goto
statement implicite.



> > 2. Never branch into the middle of another control structure
> > (if, for, while, etc.)
>
> See the Knuth paper (reference from me upthread) for a
> counterexample. s/Never/Almost never/
>
> > 3. Don't use goto if another control structure can do the same
> > job.
>
> This one I can accept.
>

A good design will evacuate details of "how to do" into a deeper level
to hide it from "what is to do". That will increase the readability
and security by hiding details while increasing the maintenceability
and decreasing the time needed to debug the functionality.

isdoable = init();
while (isdoable && primary())
while(!!(isdoable = secondary())
if (!realwork()) {
if (errorhandling())
isdoable = FALSE;
break;
}
cleanup();
return;

Keith Thompson

unread,
Jan 6, 2006, 3:48:16 PM1/6/06
to
"Herbert Rosenau" <os2...@pc-rosenau.de> writes:
> On Wed, 4 Jan 2006 15:51:08 UTC, "John Bode" <john...@my-deja.com>
> wrote:
>
>> IME, there are cases where a goto is useful, but they are few and far
>> between.
>
> Please name one! Only one. In 25 years of programming in C i have
> never found a single one. I've written small, middle and really big
> applications, I've written drivers, whole OSes for realtime
> environments but have never found a reason to write goto.

A goto statement is never necessary in a language that has a minimal
set of structured control constructs (there's a theorem to that
effect), but it *can* be useful at times.

For example:

void foo(void)
{
foo_type *foo = NULL;
bar_type *bar = NULL;
baz_type *baz = NULL;

foo = init_foo_type(); /* returns NULL on error */
if (foo == NULL) goto ERROR;

bar = init_bar_type();
if (bar == NULL) goto ERROR;

baz = init_baz_type();
if (baz == NULL) goto ERROR;

/*
* A bunch of code that uses foo, bar, and baz.
*/

ERROR:
if (baz != NULL) cleanup_baz_type(baz);
if (bar != NULL) cleanup_bar_type(bar);
if (foo != NULL) cleanup_foo_type(foo);
}

Of course it could be restructured. The most obvious way to do so is
to use nested if statements, with the nesting level becoming deeper as
the number of initializations increases. Another approach is to
replace each "goto ERROR;" with a return statement; the second and
third would have to be preceded by cleanup calls.

Richard Tobin

unread,
Jan 6, 2006, 4:43:39 PM1/6/06
to
In article <lny81t1...@nuthaus.mib.org>,
Keith Thompson <ks...@mib.org> wrote:

> void foo(void)
> {
> foo_type *foo = NULL;
> bar_type *bar = NULL;
> baz_type *baz = NULL;
>
> foo = init_foo_type(); /* returns NULL on error */
> if (foo == NULL) goto ERROR;
>
> bar = init_bar_type();
> if (bar == NULL) goto ERROR;
>
> baz = init_baz_type();
> if (baz == NULL) goto ERROR;
>
> /*
> * A bunch of code that uses foo, bar, and baz.
> */
>
> ERROR:
> if (baz != NULL) cleanup_baz_type(baz);
> if (bar != NULL) cleanup_bar_type(bar);
> if (foo != NULL) cleanup_foo_type(foo);
> }

>Of course it could be restructured. The most obvious way to do so is
>to use nested if statements, with the nesting level becoming deeper as
>the number of initializations increases.

Which (contrary to Herbert Rosenau's assertion) would make the code
less readable, at least to me.

>Another approach is to
>replace each "goto ERROR;" with a return statement; the second and
>third would have to be preceded by cleanup calls.

Which would make maintenance harder and increase the risk of errors,
since the cleanup code would have to be maintained in both places.

A rigid rule against gotos is like the rule against split infinitives:
a fetish (cf Fowler's Modern English Usage). In both cases the
solution is not a rule but good taste and experience.

-- Richard

Skarmander

unread,
Jan 6, 2006, 5:11:10 PM1/6/06
to
Herbert Rosenau wrote:
<snip>

> A good design will evacuate details of "how to do" into a deeper level
> to hide it from "what is to do". That will increase the readability
> and security by hiding details while increasing the maintenceability
> and decreasing the time needed to debug the functionality.
>
> isdoable = init();
> while (isdoable && primary())
> while(!!(isdoable = secondary())
> if (!realwork()) {
> if (errorhandling())
> isdoable = FALSE;
> break;
> }
> cleanup();
> return;
>
Hurrah, we have avoided the evil goto. In the process, we demonstrate some
other readability-decreasing features: !! to "convert" to boolean, combining
assignment and test, omitting braces around multiply-nested statements.

This is a perfect example of when a labeled break would come in handy. C
does not have them; a goto would do.

if (!init()) goto do_cleanup;
while (primary()) {
while (secondary()) {
if (!realwork()) {
if (errorhandling()) goto do_cleanup;
break;
}
}
}
do_cleanup:
cleanup();
return;

Evacuating details notwithstanding, I can't come up with arguments as to why
a version that uses a control variable should be better design than one
without it.

Holy wars have been waged on this topic for a very long time now; although
one is free to prefer one style over another, it is wise to consider the
possibility that there are not altogether many rational arguments in favor
or against either side.

This example in particular boils down to whether you think goto is bad or
not. You can waffle about design all you want, but this is code at the most
basic level. Same nesting, same functions, almost the same line count --
what you prefer is really a matter of taste.

S.

Chuck F.

unread,
Jan 6, 2006, 4:02:00 PM1/6/06
to
Herbert Rosenau wrote:
> "Chuck F. " <cbfal...@yahoo.com> wrote:
>
... snip objection to backward goto ...

>
>> Counterexample:
>>
>> preliminarysetup();
>> outer: while (condition1) {
>> dosumthing();
>> while (condition2) {
>> dosumthingelse();
>> if (condition3) goto outer;
>
> Very bad design!
>
>> domore();
>> }
>> dostillmore();
>> }
>>
>> The goto cannot be replaced by break or continue, and even if
>> it could the goto is clearer.
>
> Redesign the whole block and you will avoid the label and the
> goto statement implicite.

Oh - and how would you redesign it, bearing in mind that condition3
is in the nature of a local abort and that the emphasis is on doing
things? The idea is clarity, and I suspect whatever you are
thinking of will tend to obfuscate.

Richard Heathfield

unread,
Jan 6, 2006, 5:42:25 PM1/6/06
to
Chuck F. said:

> Oh - and how would you redesign it, bearing in mind that condition3
> is in the nature of a local abort and that the emphasis is on doing
> things? The idea is clarity, and I suspect whatever you are
> thinking of will tend to obfuscate.

I'd start off by choosing much better names.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

Herbert Rosenau

unread,
Jan 7, 2006, 4:26:04 PM1/7/06
to
On Fri, 6 Jan 2006 21:02:00 UTC, "Chuck F. " <cbfal...@yahoo.com>
wrote:

> Herbert Rosenau wrote:


> > "Chuck F. " <cbfal...@yahoo.com> wrote:
> >
> ... snip objection to backward goto ...
> >
> >> Counterexample:
> >>
> >> preliminarysetup();
> >> outer: while (condition1) {
> >> dosumthing();
> >> while (condition2) {
> >> dosumthingelse();
> >> if (condition3) goto outer;
> >
> > Very bad design!
> >
> >> domore();
> >> }
> >> dostillmore();
> >> }
> >>
> >> The goto cannot be replaced by break or continue, and even if
> >> it could the goto is clearer.
> >
> > Redesign the whole block and you will avoid the label and the
> > goto statement implicite.
>
> Oh - and how would you redesign it, bearing in mind that condition3
> is in the nature of a local abort and that the emphasis is on doing
> things? The idea is clarity, and I suspect whatever you are
> thinking of will tend to obfuscate.
>

Break down the whole complicate thing in levels:
level description
1 show up WHAT is to do
when needed recurse level 1
2 how is it done
when needed recurse level 1 until
there is only one single step to do
or the number of steps is very short
and unconditional.

This can always be done by creating functions hiding details of what
is to do respective how is the detail done. This can (but must not)
reduce a number of if, for, while statements but will avoid any goto
by design.

Break down the whole program in a sequence of single steps. Code each
single step as own function whereas each function itself will
break down the whole function in a sequence wheras.....
..... until a single function fits on a screen size and has not more
direct nested control statemens as 3 or 4.

You would easy learn by that that C has some levels of visibility of
variables and functions and you'll learn to use that well.

After you has learned programming in C you would have to learn
programming using C. Then you would be ready to use C instead of
basic, FORTRAN or cobol or pure assembly and forget about goto and its
existence because you'll never see a need for.

Herbert Rosenau

unread,
Jan 7, 2006, 4:26:04 PM1/7/06
to
On Fri, 6 Jan 2006 20:48:16 UTC, Keith Thompson <ks...@mib.org> wrote:

> A goto statement is never necessary in a language that has a minimal
> set of structured control constructs (there's a theorem to that
> effect), but it *can* be useful at times.
>
> For example:

Crappy design:



> void foo(void)
> {
> foo_type *foo = NULL;
> bar_type *bar = NULL;
> baz_type *baz = NULL;
>
> foo = init_foo_type(); /* returns NULL on error */
> if (foo == NULL) goto ERROR;
>
> bar = init_bar_type();
> if (bar == NULL) goto ERROR;
>
> baz = init_baz_type();
> if (baz == NULL) goto ERROR;
>
> /*
> * A bunch of code that uses foo, bar, and baz.
> */
>
> ERROR:
> if (baz != NULL) cleanup_baz_type(baz);
> if (bar != NULL) cleanup_bar_type(bar);
> if (foo != NULL) cleanup_foo_type(foo);
> }

The same without goto:

if ((foo = init_foo_type())
&& (bar = init_bar_type())
&& (baz = init_baz_type())
) {
/* work */
}
cleanup_baz_type(baz);
cle......

or avoiding the big if and breaking the whole work down into different
levels, hiding too much details but giving better overview of the real
work:

static int init_types(int **foo, int **bar, int **baz) {
return (*foo = init_foo_type())
&& (*bar = init_bar_type())
&& (*baz = init_baz_type());
}

static void cleanup_types(.... like init_types but cleanup.......
:
:


:
void foo(void) {
foo_type *foo = NULL;
bar_type *bar = NULL;
baz_type *baz = NULL;

if (init_types(&foo, &bar, &baz)) {
do_work(....);
}
cleanup_types(&foo, &bar, &baz);
}

I would prefere the second choice when runtime is not really critical
because it makes anything more maintenanceable and more readable.

> Of course it could be restructured. The most obvious way to do so is
> to use nested if statements, with the nesting level becoming deeper as
> the number of initializations increases. Another approach is to
> replace each "goto ERROR;" with a return statement; the second and
> third would have to be preceded by cleanup calls.
>

I would reduce the number of if statements and increasing the
readability, and the time testing is needed. When init is tested well
it can be ignored easy during forthgoing debug becaus it is known as
ready for GA. The same is for the real work......

I like to hide so much details as possible because it is after 3 years
untouched sources more easy to extend or even change the functionality
when details are hidden until there is a real need to know about them.
So looking at WHAT is going on and looking on HOW is it done only when
there is a need for makes anything much easier to understund.

Herbert Rosenau

unread,
Jan 7, 2006, 4:26:05 PM1/7/06
to
On Fri, 6 Jan 2006 22:11:10 UTC, Skarmander <inv...@dontmailme.com>
wrote:

You're right that my example is not the best. But in the short time I
found nothing that I were able to use to make from a nonsense a real
good design. For a blind hack of code that makes as such no sense it
was the best to show up other code without sense but avoiding goto.

Real design starts at much higher level and will avoid some constructs
before there is a chance to write a single statement.

!! is a possibility to save typing (and mistyping, e.g. like = instead
of ==). True, yes I do never take consideration of beginners in
learning C because one has to learn the language by using it.

Yes, I don't like empty lines whenever there is a chance to avoid one,
except an empty line can stand for self declaring documentation saying
there starts a new logical block of execution. Yes, I avoid {}
whenever possible because that gives up to 2 more lines on the same
screen page.
But for that my editor knows how to indent right and it will prove the
matching of braces every time I ask it for. True, this all is at least
a question of style but avoiding goto and longjump is never. You would
know that when you have written one singe project that has not only to
be failsave but has to save human live in any condition and not only
some money.

Keith Thompson

unread,
Jan 7, 2006, 5:20:27 PM1/7/06
to

That assumes each initialization can be done in a single expression
statement. That happens to be true in my example, but it needn't be,
and your transformation won't work for more complex cases. Sure, you
could write your own init_*() functions to guarantee that each piece
of initialization can be done with a single function call, but that
just moves the complexity somewhere else (which could be a good
thing).

Also, you're calling the cleanup_*() functions without checking
whether their arguments are non-NULL.

> or avoiding the big if and breaking the whole work down into different
> levels, hiding too much details but giving better overview of the real
> work:
>
> static int init_types(int **foo, int **bar, int **baz) {
> return (*foo = init_foo_type())
> && (*bar = init_bar_type())
> && (*baz = init_baz_type());
> }
>
> static void cleanup_types(.... like init_types but cleanup.......
> :
> :
> :
> void foo(void) {
> foo_type *foo = NULL;
> bar_type *bar = NULL;
> baz_type *baz = NULL;
>
> if (init_types(&foo, &bar, &baz)) {
> do_work(....);
> }
> cleanup_types(&foo, &bar, &baz);
> }
>
> I would prefere the second choice when runtime is not really critical
> because it makes anything more maintenanceable and more readable.

Now you're creating new functions that are called only once. That's
not *necessarily* a bad idea, but it sometimes can lead to what you
might call structured spaghetti.

[snip]

I rarely, if ever, use gotos myself, and if I were writing the above
code I'd probably try to find a way to avoid them. Indiscriminate use
of gotos is undoubtedly dangerous. Careful use of gotos *can* be ok,
particularly if they're used only to work around a missing language
feature such as exception handling or multi-level break. And of
course it's not the least bit difficult to write horrendously bad code
without using a single goto.

Digression:

We're able to avoid gotos for the most part because the language gives
us higher level control structures. This is less true for data
structures than for control structures. A goto in a control structure
is analagous to a pointer as a data structure. In both cases, the
programmer is responsible for keeping everything consistent, and
failure to do so can be disastrous. Using explicit gotos to implement
a higher-level control structure is frowned upon; using explicit
pointers to implement a higher-level data structure (such as a linked
list or binary tree) is standard practice.

Skarmander

unread,
Jan 7, 2006, 7:12:01 PM1/7/06
to
I don't doubt it's possible to call some approach to design "real design"
and coincidentally have this approach avoid all cases where goto could come
in handy.

Not that it's easy, mind you. If high-level "real design" impacts how code
is written at the lowest level, there is something suspicious about it.

> !! is a possibility to save typing (and mistyping, e.g. like = instead
> of ==). True, yes I do never take consideration of beginners in
> learning C because one has to learn the language by using it.
>

I'm not a beginner and I do know perfectly what !! means. Knowing what it
means and wanting to use it are two different things (as you know, of
course, through avoiding goto. :-)

The = vs. == thing is indeed another wart of C best avoided, but this at
least is something even the beginners quickly grow wise to. There's not
enough code out there using the !! trick to make it as readable. You can
parse it, but it takes time. How much time code takes to *type* is all but
insignificant (I'm sure managers will tell you otherwise, but most of those
managers couldn't program if their lives depended on it, let alone judge
coding techniques.)

> Yes, I don't like empty lines whenever there is a chance to avoid one,
> except an empty line can stand for self declaring documentation saying
> there starts a new logical block of execution. Yes, I avoid {}
> whenever possible because that gives up to 2 more lines on the same
> screen page.

Well, this is another one of those holy war things we'd best not touch and
chalk up to personal preference. Those things probably make a difference one
way or another, but not enough to quibble about.

> But for that my editor knows how to indent right and it will prove the
> matching of braces every time I ask it for. True, this all is at least
> a question of style but avoiding goto and longjump is never. You would
> know that when you have written one singe project that has not only to
> be failsave but has to save human live in any condition and not only
> some money.
>

Ooh, here you go making assumptions, and we all know how dangerous that is.
You're in luck, though: I'm not going to tell you I wrote the control
program for a nuclear reactor or an X-ray scanner and used goto and
longjmp() to good effect. I wouldn't turn this into a "my application field
is more sensitive to failure than yours" debate, though; this tends to be
unproductive. Some applications that saved "some money" arguably had plenty
of impact on the quality and possibly quantity of human life, too.

Even without the benefit of this no doubt insightful experience, your
assertion is mere bluster, since you're not going to prove that the use of
goto was what condemned such a project in the past. It is an appeal to
emotion that boils down to "goto makes your project bad, and in your really
important project it's a liability".

What next? "goto kills"? I'm sure it has. So have floating-point
calculations and exceptions (in other languages). In all of these cases it
is dubious to propose the features themselves were wrong. Misapplied, yes.
Easy to misapply, certainly. Never appropriate, not necessarily.

What is true is that goto (and longjmp() even more so) are hard to use
*appropriately*. This is why goto should be avoided: if you don't know why
you're using goto and not some other control structure, you're not using it
right and should stop. Write something you can control. Better, write
something that is obvious not just to you, but to anyone of slightly less
capacity than yourself. (It is useless to write code for programmers vastly
worse than yourself, since they cannot modify what they do not understand
anyway; it is likewise useless to try and be smarter than you actually are
on a bad day, which is a much more common failing.)

Programmers do not how to use goto properly either because they've *never*
been told not to use it, or because they've *always* been told not to use
it. Yes, you can shoot yourself in the foot with goto, no question about it.
Then again, you can shoot yourself in the foot with a lot of things in C.
None of this can serve as a blanket condemnation. The pitfalls of goto are
well known, and all the arguments for and against are, too. Those who are
not familiar with them should stick with "never use goto", since it makes
the world a better place for all of us. I would be the last one to advocate
changing this happy status quo.

goto has its uses. Anyone who denies this is calling Donald Knuth wrong.
Unrestricted use of goto is harmful. Anyone who denies this is calling
Edsger Dijkstra wrong. I wouldn't take either of those men on lightly
without some very good arguments, because they usually have them handy.

I'd like to close this debate with an important remark: I can count the
number of times I've used goto in applications on the fingers of one hand,
quite unlike the number of programs I've written, for which no appendages
suffice (they would if I counted in binary, though). The count for longjmp()
stands at zero.

Why? Because goto was not the appropriate solution to the problem in almost
every case. In those cases where I used it, it was. Equivalent code not
using goto of course existed, but it was less elegant and less readable.
There aren't many legitimate uses of goto -- but where they are, it is
fanaticalism to say that they, too, should be abolished because they raise
the spectre of wrongful application. It's likewise silly to say "but you can
do that without goto". Of course. Then I can say "but you can do that
without while". It doesn't really advance things.

S.

August Karlstrom

unread,
Jan 7, 2006, 9:53:45 PM1/7/06
to
Herbert Rosenau wrote:
[snip]

> True, this all is at least
> a question of style but avoiding goto and longjump is never. You would
> know that when you have written one singe project that has not only to
> be failsave but has to save human live in any condition and not only
> some money.

I doubt that C is the right tool for safety critical programs. I think
the general problem with C is not the language itself, but that it's
used outside the system programming area.

Here is a classical quote about goto:

"As for GOTO, I have this to say:

The apprentice uses it without thinking.
The journeyman avoids it without thinking.
The master uses it thoughtfully."

Chuck F.

unread,
Jan 7, 2006, 11:27:12 PM1/7/06
to
> ...... until a single function fits on a screen size and has not

> more direct nested control statemens as 3 or 4.
>
> You would easy learn by that that C has some levels of
> visibility of variables and functions and you'll learn to use
> that well.
>
> After you has learned programming in C you would have to learn
> programming using C. Then you would be ready to use C instead of
> basic, FORTRAN or cobol or pure assembly and forget about goto
> and its existence because you'll never see a need for.

I don't think this self-aggrandizement deserves a reply. I am
quoting the whole thing to expose the foolishness.

Richard Heathfield

unread,
Jan 8, 2006, 1:23:09 AM1/8/06
to
August Karlstrom said:

> Here is a classical quote about goto:
>
> "As for GOTO, I have this to say:
>
> The apprentice uses it without thinking.
> The journeyman avoids it without thinking.
> The master uses it thoughtfully."

Unfortunately, there are way too many apprentices who think they are
masters.

Herbert Rosenau

unread,
Jan 8, 2006, 5:41:56 PM1/8/06
to
On Sat, 7 Jan 2006 22:20:27 UTC, Keith Thompson <ks...@mib.org> wrote:

> "Herbert Rosenau" <os2...@pc-rosenau.de> writes:
> > On Fri, 6 Jan 2006 20:48:16 UTC, Keith Thompson <ks...@mib.org> wrote:

> > The same without goto:
> >
> > if ((foo = init_foo_type())
> > && (bar = init_bar_type())
> > && (baz = init_baz_type())
> > ) {
> > /* work */
> > }
> > cleanup_baz_type(baz);
> > cle......
>
> That assumes each initialization can be done in a single expression
> statement. That happens to be true in my example, but it needn't be,
> and your transformation won't work for more complex cases.

Sure, the transformation was done on your exampel, not on a more
complex one. A more complex one had gotten another transformation
because it had needed another design.

Sure, you
> could write your own init_*() functions to guarantee that each piece
> of initialization can be done with a single function call, but that
> just moves the complexity somewhere else (which could be a good
> thing).

That is why I say "make a right design and some problems going away
alone.



> Also, you're calling the cleanup_*() functions without checking
> whether their arguments are non-NULL.

Hey, it is the job of a cleanup that can receive errornous data to
check it. When the design says it has to handle null pointers it must
do so. If it were impossible to receive ones it would not.



> > or avoiding the big if and breaking the whole work down into different
> > levels, hiding too much details but giving better overview of the real
> > work:
> >
> > static int init_types(int **foo, int **bar, int **baz) {
> > return (*foo = init_foo_type())
> > && (*bar = init_bar_type())
> > && (*baz = init_baz_type());
> > }
> >
> > static void cleanup_types(.... like init_types but cleanup.......
> > :
> > :
> > :
> > void foo(void) {
> > foo_type *foo = NULL;
> > bar_type *bar = NULL;
> > baz_type *baz = NULL;
> >
> > if (init_types(&foo, &bar, &baz)) {
> > do_work(....);
> > }
> > cleanup_types(&foo, &bar, &baz);
> > }
> >
> > I would prefere the second choice when runtime is not really critical
> > because it makes anything more maintenanceable and more readable.
>
> Now you're creating new functions that are called only once. That's
> not *necessarily* a bad idea, but it sometimes can lead to what you
> might call structured spaghetti.

No, it can not because C knows of different storage classes and one
should know how to use them even on functions. The design of a
translation unit is design that can even be done before the first
statement gets written.

One time functions an excellent method to refine a job from an
overview to the last detail. Each one time function will clearly be on
storage class static to document that it is never used outside this
translation unit. So until you have a need to look into the
implementation details you can surely ignore it.

My style guide is to organise each translation unit in logical blocks
- #define and #ifdef as needed to modify #included files
- #include external definitions and declarations as needed
commonly known as header files
- defining data used by other translation units but
associated to this translation unit
- defining data and macros needed on file scope but
only in this translation unit
- declaring one time functions
- declaring other static functions
- defining local functions
- defining external callable functions
(declarations are in #included header files,
giving the compiler a chance to check prototypes
agaist the definitions)
- for each function: the same as for the whole translation unit.




> [snip]
>
> I rarely, if ever, use gotos myself, and if I were writing the above
> code I'd probably try to find a way to avoid them. Indiscriminate use
> of gotos is undoubtedly dangerous. Careful use of gotos *can* be ok,
> particularly if they're used only to work around a missing language
> feature such as exception handling or multi-level break. And of
> course it's not the least bit difficult to write horrendously bad code
> without using a single goto.

As sayed I have in 25 years programming C never found a cause to write
goto. I had never missed exceptions as in C++ (maybe because my
history is another 10 years of programming in assembly on highly
different mashines before I got to learn to be a C programmer).

Yes I had missed sometimes labled break, but not really as on all
places it were useful as such the complexitiy of the whole blox was
high enough to redesign as ((a copule of) one time) functions to get
off the complexity of the problem.



> Digression:
>
> We're able to avoid gotos for the most part because the language gives
> us higher level control structures. This is less true for data
> structures than for control structures. A goto in a control structure
> is analagous to a pointer as a data structure.

No. An own function for a block of code is the same as a struct for
data. Encapsulate code to hide complexity makes more sense as it
increases the readability which increases the maintenceabiltity.

In both cases, the
> programmer is responsible for keeping everything consistent, and
> failure to do so can be disastrous. Using explicit gotos to implement
> a higher-level control structure is frowned upon;

No, not really. That decreases only the readability and avoids
manintenanceability. It is hard to find a goto and the cause for when
you have to maintenance code you've not written or you've not touched
the sources for years.

using explicit
> pointers to implement a higher-level data structure (such as a linked
> list or binary tree) is standard practice.

Yes, but even there I've seen the wrong type of linked list for the
job it had to hold for. It is easy to make the wrong desin in both
data and code. Wheras it is sometimes not so easy to rework the design
before coding starts and often nearly impossible thereafter based on
time and cost needed for.

Keith Thompson

unread,
Jan 8, 2006, 7:11:38 PM1/8/06
to
"Herbert Rosenau" <os2...@pc-rosenau.de> writes:
> On Sat, 7 Jan 2006 22:20:27 UTC, Keith Thompson <ks...@mib.org> wrote:
[...]

>> Digression:
>>
>> We're able to avoid gotos for the most part because the language gives
>> us higher level control structures. This is less true for data
>> structures than for control structures. A goto in a control structure
>> is analagous to a pointer as a data structure.
>
> No. An own function for a block of code is the same as a struct for
> data. Encapsulate code to hide complexity makes more sense as it
> increases the readability which increases the maintenceabiltity.

Except that the internals of a struct are visible to its callers; the
equivalent would be allowing the caller of a function to have access
to every individual statement within the function. The equivalent of
a function would be a structure whose members are hidden.

>> In both cases, the
>> programmer is responsible for keeping everything consistent, and
>> failure to do so can be disastrous. Using explicit gotos to implement
>> a higher-level control structure is frowned upon;
>
> No, not really. That decreases only the readability and avoids
> manintenanceability. It is hard to find a goto and the cause for when
> you have to maintenance code you've not written or you've not touched
> the sources for years.

Where does the "No, not really" comes from? I don't see how you're
disagreeing with what I wrote here.

(BTW, the words are "maintainability" and "maintain", not
"manintenanceability" and "maintenance".)

> using explicit
>> pointers to implement a higher-level data structure (such as a linked
>> list or binary tree) is standard practice.
>
> Yes, but even there I've seen the wrong type of linked list for the
> job it had to hold for. It is easy to make the wrong desin in both
> data and code. Wheras it is sometimes not so easy to rework the design
> before coding starts and often nearly impossible thereafter based on
> time and cost needed for.

Agreed. (And of course the analogy between control structures and
data structures isn't absolute, but there are some interesting things
to learn from looking at things that way.)

tmp123

unread,
Jan 8, 2006, 6:08:49 AM1/8/06
to
August Karlstrom wrote:
> I doubt that C is the right tool for safety critical programs. I think
> the general problem with C is not the language itself, but that it's
> used outside the system programming area.


Sorry, could you expand a few more this part?.

Thanks.

Chris Hills

unread,
Jan 9, 2006, 6:55:35 AM1/9/06
to
In article <1136367386....@g43g2000cwa.googlegroups.com>,
tmp123 <tmp...@menta.net> writes
>
>Richard Heathfield wrote:
>> tmp123 said:
>>
>> > Thus, I suggest you to review the usage of "try"/"catch"/... (forget my
>> > sugestion if you know them).
>>
>> They don't exist in C.
>
>
>Yes, you have reason, I forget to remark it (a good reason to start in
>C++).
>
>However, I'm sure you known it is posible a workaround with a few
>macros like:
>
>#define TRY if(...(setjmp(...
>#define CATCH else
>#define RAISE logjmp(...
>
>Kind regards.
>

Most standards that ban got also ban setjmp and logjmp

--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills Staffs England /\/\/\/\/
/\/\/ ch...@phaedsys.org www.phaedsys.org \/\/\
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

webs...@gmail.com

unread,
Jan 9, 2006, 8:44:25 AM1/9/06
to
John Bode wrote:
> M.B wrote:
> > Need some of your opinion on an oft beaten track
> > We have an option of using "goto" in C language, but most testbooks
> > (even K&R) advice against use of it.
> > My personal experience was that goto sometimes makes program some more
> > cleaner and easy to understand and also quite useful (in error handling
> > cases).

> > So why goto is outlawed from civilized c programmers community.
>
> IME, there are cases where a goto is useful, but they are few and far
> between. I have no problems with gotos provided some basic rules are
> followed:
>
> 1. Branch forward only.

This is nonsense.

> 2. Never branch into the middle of another control structure (if, for,
> while, etc.)

There are cases where this leads to a performance improvement to do so.

> 3. Don't use goto if another control structure can do the same job.

You can always use another control structure -- the question is whether
or not doing so makes the code more complicated or slower.

I personally follow only one rule regarding goto: avoid using it unless
using it leads to either clearer code or faster (executing) code. This
rule alone is sufficient to make the use of goto fairly uncommon in my
code to the point of "spaghetti code" never being an issue. (If
there's one exception it would have to be parsers -- but in those cases
even the cleanest control structures don't actually lead to a clearer
representation of the parser.)

The typical cases where goto is useful: 1) when escaping from more than
one level of loop control, 2) when you have more than one "clean up and
return" code fragment that can be reached from even more scenarios
(typically "clean up and return error" versus "clean up and return
sucess".) 3) Any state machine (switch often doesn't make things
clearer, and can make things horrendously slower.) 4) Starting a
performance critical tight loop from the middle.

> ISTR some verbiage in H&S that the presence of a goto can hinder some
> compiler optimizations.

There may be some weak older generation compilers for which that is
true. However, most modern compilers actually internally transform all
control structures to "if ... goto" anyways.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/

Chris Dollin

unread,
Jan 9, 2006, 8:56:00 AM1/9/06
to
webs...@gmail.com wrote:

> I personally follow only one rule regarding goto: avoid using it unless
> using it leads to either clearer code or faster (executing) code. This
> rule alone is sufficient to make the use of goto fairly uncommon in my
> code to the point of "spaghetti code" never being an issue. (If
> there's one exception it would have to be parsers -- but in those cases
> even the cleanest control structures don't actually lead to a clearer
> representation of the parser.)

I've never had to use a goto in a parser; could you unpack the reasons
why you've wanted one? [email if it's likely to be wildly off-topic.]

--
Chris "believes seventeen improbable things before coffee" Dollin
Seventeen, forty-two - what else is there?

Joseph Dionne

unread,
Jan 9, 2006, 9:07:06 AM1/9/06
to
Chris Dollin wrote:
> webs...@gmail.com wrote:
>
>
>>I personally follow only one rule regarding goto: avoid using it unless
>>using it leads to either clearer code or faster (executing) code. This
>>rule alone is sufficient to make the use of goto fairly uncommon in my
>>code to the point of "spaghetti code" never being an issue. (If
>>there's one exception it would have to be parsers -- but in those cases
>>even the cleanest control structures don't actually lead to a clearer
>>representation of the parser.)
>
>
> I've never had to use a goto in a parser; could you unpack the reasons
> why you've wanted one? [email if it's likely to be wildly off-topic.]
>

As a *troll* I use goto often to increase execution speed, easing code
readability mostly in library utilities that I write once and never look at again.

Here is my general structure.

int func(arguments)
{
int error = 0;

/* lengthy function code listing */

/* at various "test" points in function the test below exists */
if (something_aint_right)
{
error = 1;
goto FINAL_func;
}

FINAL_func:
/* clean up any local resources, like malloc() calls, device opens, etc */

if (error)
{
/* any aditional code for error processing here. */
}

return(error);
}


This technique simple allows me to not code multiple in line error condition
tests, and give me the ability to immediately jump out when things go bad.

webs...@gmail.com

unread,
Jan 9, 2006, 1:36:44 PM1/9/06
to
Chris Dollin wrote:
> webs...@gmail.com wrote:
> > I personally follow only one rule regarding goto: avoid using it unless
> > using it leads to either clearer code or faster (executing) code. This
> > rule alone is sufficient to make the use of goto fairly uncommon in my
> > code to the point of "spaghetti code" never being an issue. (If
> > there's one exception it would have to be parsers -- but in those cases
> > even the cleanest control structures don't actually lead to a clearer
> > representation of the parser.)
>
> I've never had to use a goto in a parser; could you unpack the reasons
> why you've wanted one? [email if it's likely to be wildly off-topic.]

Well, I measure the performance of the code I write, and I have never
used/figured out yacc or bison or any of those tools. Most parsing
that I implement boil down to what I would call state machines with
counters. The gotos are for state transitions. The typical thing that
I've seen is a switch statement wrapped in a while(), but as I
mentioned switch is *extremely* slow as compared to a goto. Goto costs
the CPU almost nothing (at worst 1-clock of empty decode) as compared
to a break->continue->switch (essentially a goto, then a comparison, a
branch, then an indirect branch) which you pay for in the "well
structured" parsers.

Chuck F.

unread,
Jan 9, 2006, 3:35:44 PM1/9/06
to
webs...@gmail.com wrote:
> John Bode wrote:
>
... snip ...
>
>> ISTR some verbiage in H&S that the presence of a goto can
>> hinder some compiler optimizations.
>
> There may be some weak older generation compilers for which that
> is true. However, most modern compilers actually internally
> transform all control structures to "if ... goto" anyways.

The exception is machine architectures with special instructions
for a looping construct. This includes the HP3000, which has a
special 'for' construct, and the 808x6, which has a 'rep' (repeat)
construct.

Keith Thompson

unread,
Jan 9, 2006, 4:37:17 PM1/9/06
to
webs...@gmail.com writes:
[snip]

> You can always use another control structure -- the question is whether
> or not doing so makes the code more complicated or slower.
>
> I personally follow only one rule regarding goto: avoid using it unless
> using it leads to either clearer code or faster (executing) code. This
> rule alone is sufficient to make the use of goto fairly uncommon in my
> code to the point of "spaghetti code" never being an issue. (If
> there's one exception it would have to be parsers -- but in those cases
> even the cleanest control structures don't actually lead to a clearer
> representation of the parser.)
>
> The typical cases where goto is useful: 1) when escaping from more than
> one level of loop control, 2) when you have more than one "clean up and
> return" code fragment that can be reached from even more scenarios
> (typically "clean up and return error" versus "clean up and return
> sucess".) 3) Any state machine (switch often doesn't make things
> clearer, and can make things horrendously slower.) 4) Starting a
> performance critical tight loop from the middle.

In the latter case, I'd probably prefer to use Duff's Device (with a
big fat comment block explaining why I really really needed to do
this).

>> ISTR some verbiage in H&S that the presence of a goto can hinder some
>> compiler optimizations.
>
> There may be some weak older generation compilers for which that is
> true. However, most modern compilers actually internally transform all
> control structures to "if ... goto" anyways.

I actually don't know much about the *current* state of compilers, but
the one I worked on (not a C compiler) actually used higher-level
control structures in its intermediate code. A loop, for example, was
explicitly represented as a loop; this made hoisting more
straightforward. ("Hoisting" refers to taking an expression evaluated
inside a loop and moving its evaluation outside the loop.) Gotos were
allowed, but they would make the optimizer's job more difficult.

Richard Tobin

unread,
Jan 9, 2006, 4:45:13 PM1/9/06
to
In article <saidnXtfIsJ...@maineline.net>,
Chuck F. <cbfal...@maineline.net> wrote:

>> There may be some weak older generation compilers for which that
>> is true. However, most modern compilers actually internally
>> transform all control structures to "if ... goto" anyways.

>The exception is machine architectures with special instructions
>for a looping construct. This includes the HP3000, which has a
>special 'for' construct, and the 808x6, which has a 'rep' (repeat)
>construct.

I think you're mixing up two separate parts of the compiler here. In
a typical modern compiler, the control structures will be converted to
linear blocks with jumps between them regardless of the target
architecture. If appropriate, some of those blocks will result in
generation of "rep" instructions in a later phase.

-- Richard

Christian Bau

unread,
Jan 9, 2006, 7:10:23 PM1/9/06
to
In article <1136831804....@f14g2000cwb.googlegroups.com>,
webs...@gmail.com wrote:

One suggestion for a C extension:

continue <expr>;

which can be used within a switch statement: It evaluates the
expression, then repeats the original switch statement with the value of
<expr> instead of the original value of the switch statement. Obviously
this can be optimised to a simple jump instruction if <expr> is a
constant expression. Would that get rid of your goto's?

(This extension wouldn't break any existing code, since it is impossible
in the current C language to have a 'continue' followed by anything but
a semicolon).

Christian Bau

unread,
Jan 9, 2006, 7:12:13 PM1/9/06
to
In article <saidnXtfIsJ...@maineline.net>,
"Chuck F. " <cbfal...@yahoo.com> wrote:

> webs...@gmail.com wrote:
> > John Bode wrote:
> >
> ... snip ...
> >
> >> ISTR some verbiage in H&S that the presence of a goto can
> >> hinder some compiler optimizations.
> >
> > There may be some weak older generation compilers for which that
> > is true. However, most modern compilers actually internally
> > transform all control structures to "if ... goto" anyways.
>
> The exception is machine architectures with special instructions
> for a looping construct. This includes the HP3000, which has a
> special 'for' construct, and the 808x6, which has a 'rep' (repeat)
> construct.

I bet good compilers will still _first_ translate everything into "if
... goto" and _then_ find situations where special machine instructions
can be used. For example, cases where the x86 "rep" prefix can be used
are quite rare.

webs...@gmail.com

unread,
Jan 9, 2006, 8:01:11 PM1/9/06
to

Yes it would -- I think we've discussed this here before, and I
endorsed that or a similar change as well. But I can use goto and an
extra label today ... so, the value of this may not be extremely high.

Randy Howard

unread,
Jan 9, 2006, 9:47:57 PM1/9/06
to
Christian Bau wrote
(in article
<christian.bau-50C...@slb-newsm1.svr.pol.co.uk>):

> For example, cases where the x86 "rep" prefix can be used
> are quite rare.

Not at all. Anytime you use memcpy() with a large len
parameter, it can be used to very good effect. memcmp() is
another.

However, I can't come up with a good example offhand for using
rep during goto or switch evaluation, but there probably are a
few.


--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw
How 'bout them Horns?

Jordan Abel

unread,
Jan 9, 2006, 10:19:48 PM1/9/06
to

"goto case" would be possibly a more obvious way to implement the
functionality described.

webs...@gmail.com

unread,
Jan 9, 2006, 10:25:12 PM1/9/06
to
Randy Howard wrote:

> Christian Bau wrote:
> > For example, cases where the x86 "rep" prefix can be used
> > are quite rare.
>
> Not at all. Anytime you use memcpy() with a large len
> parameter, it can be used to very good effect.

Well, the real question here is: what do you mean by "good effect"? I
think a lot of x86 compilers *DO* use REP MOVSD here, but they are all
slower than the best method which is to operate in larger load and
store blocks. AMD gives some same code on their site somewhere that
demonstrates how this is done -- you can truly saturate the BUS this
way.

> [...] memcmp() is another.

I doubt that REP SCASB compares well with Mycroft's trick, but again, I
conceed that a lot of compilers do it this way. You might as well
complete the circle: memset could be implemented as REP STOS*.

> However, I can't come up with a good example offhand for using
> rep during goto or switch evaluation, but there probably are a
> few.

The REP prefix can only be applied to the LODS* STOS* and SCAS*
instructions, which are really just block memory operations. Goto and
switch could only be involved if the compiler massively simplified your
control structures down to the equivalent of memcpy, or memcmp, and
then actively made the choice to emit these instructions in those
cases. Its actually just as likely that a compiler emitted a REP MOVS*
when performing a struct copy.

Stan Milam

unread,
Jan 9, 2006, 11:30:21 PM1/9/06
to
M.B wrote:
> Guys,

> Need some of your opinion on an oft beaten track
> We have an option of using "goto" in C language, but most testbooks
> (even K&R) advice against use of it.
> My personal experience was that goto sometimes makes program some more
> cleaner and easy to understand and also quite useful (in error handling
> cases).
> So why goto is outlawed from civilized c programmers community.
>
> is there any technical inefficiency in that.
>
> Thank you
>

I have religiously refused to use goto in a C program (I've been forced
to use it in COBOL), with this one exception. I found it a great way to
handle exception handling where I was setting up the environment for a
complicated program. If something went wrong on the way in it got
messier the further in you went. The goto provided an elegant solution.
However, I advise extreme judicious use of goto. The example is not
complete, but it is standard C if you ignore the 3rd party library
functions.

if ( ( dans_fp = fopen( dansfile_buf, "r+b" ) ) == NULL ) {
msg = "Error: Unable to open Dan's Report File.";
goto exception_1;
}

/******************************************************************/
/* Open the extract file reading. */
/******************************************************************/

else if ( ( extract_fp = fopen( extract_buf, "r" ) ) == NULL ) {
msg = "Error: Unable to open Ladder Extract file.";
goto exception_2;
}

/******************************************************************/
/* Open the ladder file as output. */
/******************************************************************/

else if ( ( ladder_fp = fopen( input_buf, "w" ) ) == NULL ) {
msg = "Error: Unable to open Ladder Input file.";
goto exception_3;
}

/******************************************************************/
/* Create the index tree. */
/******************************************************************/

else if ((tree = cbcreate(index,DEFAULT_COMPARE, 1024)) == NULL) {
msg = "Error: Unable to create ladder index file.";
goto exception_4;
}

/******************************************************************/
/* Now, build the ladder index. */
/******************************************************************/

if ( build_ladder_index( tree, dans_fp ) == EXIT_FAILURE ) {
msg = "Error: Unable to build ladder index file.";
goto exception_5;
}
else {

/**************************************************************/
/* Do normal processing here. Code snipped. */
/**************************************************************/

/**************************************************************/
/* Close everything down normally. */
/**************************************************************/

fclose( dans_fp );
fclose( extract_fp );
fclose( ladder_fp );
cbclose( tree );
remove( index );

}
return EXIT_SUCCESS;

/**********************************************************************/
/* Here I deal with the exceptions. They are structured to undo any */
/* opens and file creations, and to print the proper message. */
/**********************************************************************/

exception_5:
cbclose( tree );
remove( index );
exception_4:
fclose( ladder_fp );
remove( input_buf );
exception_3:
fclose( extract_fp );
exception_2:
fclose( dans_fp );
exception_1:
beep();
wn_msg( msg );
return EXIT_FAILURE;

Chuck F.

unread,
Jan 9, 2006, 11:24:29 PM1/9/06
to

A compiler is a compiler, and includes whatever phases or passes
are needed to go from source to executable. Code generation and
optimization is part of that.

webs...@gmail.com

unread,
Jan 10, 2006, 1:37:10 AM1/10/06
to

Yes, but that would allow jumping inside from outside of the switch,
which is not likely to promote better structure. (Its more flexible,
but goto is always more flexible -- that's not the point.) Personally,
either one accomplishes the same thing for me, so I would accept
whichever one was added to the language.

Richard Tobin

unread,
Jan 10, 2006, 7:49:03 AM1/10/06
to
In article <1136875030.3...@g49g2000cwa.googlegroups.com>,

<webs...@gmail.com> wrote:
>> "goto case" would be possibly a more obvious way to implement the
>> functionality described.

>Yes, but that would allow jumping inside from outside of the switch,

Since you can have multiple switch statements with the same cases,
you would probably want to prohibit that anyway.

-- Richard

Richard Tobin

unread,
Jan 10, 2006, 7:54:47 AM1/10/06
to
In article <x_SdnUj0AL4A2l7e...@maineline.net>,
Chuck F. <cbfal...@maineline.net> wrote:

>>>> There may be some weak older generation compilers for which
>>>> that is true. However, most modern compilers actually
>>>> internally transform all control structures to "if ... goto"
>>>> anyways.

>>> The exception is machine architectures with special
>>> instructions for a looping construct. This includes the
>>> HP3000, which has a special 'for' construct, and the 808x6,
>>> which has a 'rep' (repeat) construct.

>> I think you're mixing up two separate parts of the compiler
>> here. In a typical modern compiler, the control structures will
>> be converted to linear blocks with jumps between them regardless
>> of the target architecture. If appropriate, some of those
>> blocks will result in generation of "rep" instructions in a
>> later phase.

>A compiler is a compiler, and includes whatever phases or passes
>are needed to go from source to executable. Code generation and
>optimization is part of that.

That's true, but irrelevant. You said that machines like the HP3000
were an exception to compilers transforming control structures to
gotos. They aren't. They do such a transformation, but transform it
back again.

-- Richard

Randy Howard

unread,
Jan 10, 2006, 8:01:21 AM1/10/06
to
webs...@gmail.com wrote
(in article
<1136863512....@g47g2000cwa.googlegroups.com>):

> Randy Howard wrote:
>> Christian Bau wrote:
>>> For example, cases where the x86 "rep" prefix can be used
>>> are quite rare.
>>
>> Not at all. Anytime you use memcpy() with a large len
>> parameter, it can be used to very good effect.
>
> Well, the real question here is: what do you mean by "good effect"? I
> think a lot of x86 compilers *DO* use REP MOVSD here, but they are all
> slower than the best method which is to operate in larger load and
> store blocks. AMD gives some same code on their site somewhere that
> demonstrates how this is done -- you can truly saturate the BUS this
> way.

That's quite true, and I've done it. A few years ago I was
asked to write a multi-threaded tool to do that very thing to
memory back when hyperthreading first started showing up in SMP
server hardware, and I well remember employing quite a few
different methods, including the one AMD recommended. However,
the discussion here was uses for rep.

BTW, even the simple speedup mentioned above wasn't used by
Microsoft's compiler at the time, yet gcc did.

>> [...] memcmp() is another.
>
> I doubt that REP SCASB compares well with Mycroft's trick, but again, I
> conceed that a lot of compilers do it this way. You might as well
> complete the circle: memset could be implemented as REP STOS*.

If you want to list all possible uses of it, knock yourself out.
Around late 2000, Microsoft's memcmp() implementation was
horribly bad and I easily beat it by 40% with a homegrown
implementation and about 20 minutes worth of work with inline
asm. I'd certainly hope they've improved since then, but I
haven't played that game in quite a while.

Dag-Erling Smørgrav

unread,
Jan 10, 2006, 8:13:31 AM1/10/06
to
Randy Howard <randy...@FOOverizonBAR.net> writes:

> Christian Bau wrote:
> > For example, cases where the x86 "rep" prefix can be used are
> > quite rare.
> Not at all. Anytime you use memcpy() with a large len parameter, it
> can be used to very good effect. memcmp() is another.

Not really. You get better performance from unrolling the loop a
little, and using FPU / MMX / SSE registers when available.

DES
--
Dag-Erling Smørgrav - d...@des.no

Randy Howard

unread,
Jan 10, 2006, 9:07:51 AM1/10/06
to
Dag-Erling Smørgrav wrote
(in article <8664osc...@xps.des.no>):

I wasn't referring to a drag race. You can all put your
professional pre-optimization hats away.

Jordan Abel

unread,
Jan 10, 2006, 9:48:39 AM1/10/06
to
On 2006-01-10, webs...@gmail.com <webs...@gmail.com> wrote:
> Jordan Abel wrote:
>>
>> "goto case" would be possibly a more obvious way to implement the
>> functionality described.
>
> Yes, but that would allow jumping inside from outside of the switch,

Or you could say it doesn't - it's your extension.

Christian Bau

unread,
Jan 10, 2006, 6:39:26 PM1/10/06
to
In article <0001HW.BFE87C7D...@news.verizon.net>,
Randy Howard <randy...@FOOverizonBAR.net> wrote:

> Christian Bau wrote
> (in article
> <christian.bau-50C...@slb-newsm1.svr.pol.co.uk>):
>
> > For example, cases where the x86 "rep" prefix can be used
> > are quite rare.
>
> Not at all. Anytime you use memcpy() with a large len
> parameter, it can be used to very good effect. memcmp() is
> another.

No go back to the original context, and find me a _loop_ that can make
use of the "rep" prefix.

Christian Bau

unread,
Jan 10, 2006, 6:48:07 PM1/10/06
to

One reason that I forgot that was somewhere hidden in my mind for
chosing "continue": "continue" inside a switch statement is extremely
ugly. Within a loop (for, do, or while loop) "continue" and "break" both
refer to the loop being executed. Within a "switch" statement, "break"
refers to the "switch" statement, but "continue" refers to any loop that
happens to include the switch statement. I would prefer if an ordinary
"continue" statement within a switch statement were illegal, because
someone who tries to "continue" a loop from within a switch statement
might be very tempted to "break" a loop from within the same switch
statement, and that won't work.

Chuck F.

unread,
Jan 10, 2006, 9:13:45 PM1/10/06
to
Richard Tobin wrote:
> <webs...@gmail.com> wrote:
>
>>> "goto case" would be possibly a more obvious way to
>>> implement the functionality described.
>
>> Yes, but that would allow jumping inside from outside of the
>> switch,
>
> Since you can have multiple switch statements with the same
> cases, you would probably want to prohibit that anyway.

This is getting OT for c.l.c. comp.std.c would be suitable.

Chuck F.

unread,
Jan 10, 2006, 9:17:12 PM1/10/06
to

No, I said that some machine had looping instructions which a
compiler could use in the code generation phase. They don't have
to. At least that is what I meant.

Chuck F.

unread,
Jan 10, 2006, 9:27:00 PM1/10/06
to
Christian Bau wrote:
>
... snip ...

>
> No go back to the original context, and find me a _loop_ that
> can make use of the "rep" prefix.

size_t slgh(const char *s)
{
const char *start = s;

while (*s++) continue;
return s - start;
}

can probably use repnz to advantage.

Skarmander

unread,
Jan 11, 2006, 8:18:28 AM1/11/06
to

What, forbid something because it's counterintuitive? That's decidedly
non-C. Think of the programmers who've made good use of this! Well, some use
of this. For some reason.

S.

Thad Smith

unread,
Jan 13, 2006, 1:52:37 AM1/13/06
to
I received an email question on my earlier posting. It is being
answered here. Read here, post here.

Thad Smith wrote:

> In general, there is some inefficiency with the elimination of goto. In
> order to eliminate goto, you often have to implement additional
> variables or flags to carry information from an inner loop to the
> outside in order to stop intermediate processing, which is not needed if
> you simply jump directly out of a loop. Also, there tends to be some
> code duplication. Some people, such as I, cheat by returning from a
> function more than one place in the body, a violation of the strict
> structured approach.

The responder wrote (via email):

> I am a novice in C. You mentioned in your message that
> you can break out of a function from more than one place,
> and it is violation of structured programming. Can you elaborate
> on how you do that and why that runs counter to good structure?

To break out of a function I execute a return statement. In general,
there may be several error cases in a function that can be handled by
simply returning an error value, so once the error determination is
made, I return an error value. The following code is then at the same
nesting level of the preceding code. Of course, I have to make sure
that I have taken care of any required cleanup before exiting. If you
want to find all the places where function returns, look for "return".

Regarding why it is not purely structured, without gotos code can be
constructed of blocks. Blocks may be combined by selection, iteration,
and sequence to form larger blocks. There are ways to reason about
program correctness using preconditions and postconditions on a block of
code, and rules to manipulate the conditions as you combine or decompose
code via the classic methods. Inserting gotos makes formal analysis
harder, at least in the general case.

A subroutine or function can be considered a code block. If you exit
from multiple points, as described above, it is equivalent to executing
a goto function_end.

Controlled use of program controls (goto, break, continue, return) can
yield code that can be easily understood and analyzed, if desired. IMO,
if a program with the additional controls could be easily converted
into an equivalent program using only the classic combining forms, its
in good form.

--
Thad

0 new messages