gotos

T. William Wells bill at proxftl.UUCP
Fri May 20 05:52:54 AEST 1988


Under ordinary circumstances, there is exactly one place where a
human C coder might use a goto.  This is to implement multi-level
breaks and continues.

I say this, having managed (and written huge chunks of) a 17,000
line software system (and that is only the part we sell, and does
not include development tools).  I have programmed in C for six
years now and have NEVER used a goto.  We have uncounted
megabytes of C code written in-house.  None of it (to my
knowledge) contains a goto.  The closest thing we have to a goto
is setjmp/longjmp, used to implement a multi-level return (and
that is a recent change, one whose contemplation caused much
debate).

With that aside, let me explain why the goto discussion is really
fruitless.  People have observed that gotos are used in a lot of
bad code.  From this it is concluded that gotos are bad.  This is
really bad logic.  Try this: programmers have been observed to
write bad code; therefore, programmers are bad!

THERE IS NOTHING WRONG WITH GOTO.  (And how do I reconcile with
my mouthing off above?  Wait and see...) The thing that is
screwed up is the control structures being implemented with the
gotos.

The whole point of the structured programming debate is this:
every program has a control structure; some of these control
structures are better than others.  Whether you use gotos or some
other language feature to implement the control structure does
not change what the control structure is nor does it affect the
goodness of the control structure.

The quality of your program is strongly influenced by the quality
of its control structures.  Furthermore, you want that control
structure to be obvious and understandable to the reader of the
program.  This implies that you use language features that make
your use of a control structure obvious.

So, the first question should be: what are the good control
structures?

The second question should be: given a particular language, how
should the control structures be implemented?

Ok, so what makes a control structure good? Well, the basic
answers are: a control structure is good if it is

    1) appropriate to solving programming problems.
    2) easy to write.
    3) easy to understand.
    4) easy to maintain.
    5) ... add your own as long as they do not contradict the above

There are obviously lots of control structures that meet these
requirements and you do not have to use all of them.  In fact,
you should pick a set of those which are most appropriate for
your programming environment and use them.  This set should be,
in some sense, a minimum one; for example, if you have two
control structures which can accomplish the same thing, but one
is easier to use than the other (for you), pick the easier one
and forget the other.  All other things being equal, a smaller
number of control structures helps make your program easier to
understand.

Now, I hope my claim about our C programs is understandable.  But
if not, here is what it amounts to: I have chosen a set of
control structures which is appropriate to programming in C, for
the kind of programming tasks that I do.  It happens that, while
my set of control structures includes multi-level breaks and
continues (which would be implemented with a goto), I have never
had need of one.  Given the amount of code I write, it seems to
me that one might never need to use an explicit goto in C code.

Now that I think of it, here is a reason to avoid naked gotos in
C code: for all other constructs, the control structure being
implemented is obvious from the keywords employed.  This is not
true for goto.  Therefore, supposing that you have found a
control structure that you have to implement using gotos in C,
you should dress the goto up.  As an example, suppose that you
are using the state machine control structure.  I normally code
it as:

	state = STATE_INIT;
	while (state != STATE_DONE) {
		switch (state) {
		case STATE_INIT:
		...
		}
	}

However, this is not the most efficient way to do it.  You could
also implement it as:

/* Wherever you see the macros state and nextstate being used,
   you will be seeing a state machine.  The state macro defines
   the start of a state.  The nextstate macro causes a transfer
   of control to another state of the same machine.  A state
   machine starts at a #define of statepref and ends with
   state(DONE).  */

#define dummy(x)        x
#define state(x)        dummy(statepref)x
#define nextstate(x)    goto dummy(statepref)x

#ifdef statepref
#undef statepref
#endif
#define statepref       STATE_
	state(INIT):
		... code for this state
		nextstate(DONE);
	... more states with the appropriate code
	state(DONE):
	... code after the state machine

(N.B.  I am aware that not all preprocessors will do what I want
here; for real portability, you would explicitly write the
prefixes.  Also, this method fails for nested state machines,
something I have occasionally had need of.)

Some of you will no doubt be thinking: but why should I go to all
this effort when I could just use the goto directly?  Well, if
this was all you did with goto, I don't really see any reason why
not (but I do think your program should include a comment saying
that you use goto for state machines and describes how you
structure it).  If, however, you have more than one way of using
goto, you should clothe the gotos somehow so that the reader of
the program knows what control structure your goto belongs to.
(After all, a while is just a disguised goto :-)



More information about the Comp.lang.c mailing list