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

Multiple exit points in a C function

2 views
Skip to first unread message

TPJ

unread,
Jun 2, 1998, 3:00:00 AM6/2/98
to

Hi All,
I recently came across a C coding guideline stating
that every function should have a single exit point (Or in other
words, avoid multiple 'return' stmts). Me and my friends are a
bit divided on supporting/not supporting this guideline. The
supporting argument for this guideline is that using multiple
returns is not structured programming and it should be avoided
at least in cases where the function returns a value.

I would be very grateful if somebody could relate their opinions/
experiences for or against this guideline. Any relevant input would
be welcome.
Thanks for Ur time and patience,
With best regards,
TPJ

--
Please remove the 'NOSPAM' from my Email ID
to reply to this message.

Kaz Kylheku

unread,
Jun 2, 1998, 3:00:00 AM6/2/98
to

On 2 Jun 1998 20:19:22 GMT, "TPJ" <to...@iaehv.nl.NOSPAM> wrote:

>Hi All,
> I recently came across a C coding guideline stating
>that every function should have a single exit point (Or in other
>words, avoid multiple 'return' stmts).

This tends to be a good guideline; however, it is often most
easily achieved by forward-branching goto statements.
It's often the case that coding guidelines that call for
a single exit point also prohibit any use of goto. :)

> Me and my friends are a
>bit divided on supporting/not supporting this guideline. The
>supporting argument for this guideline is that using multiple
>returns is not structured programming and it should be avoided
>at least in cases where the function returns a value.

That isn't much of a supporting argument. The real argument in
favor of the guideline is that it prevents mistakes whereby
a function fails to do some crucial cleanup task, such as
releasing memory. Have you ever come across code like:

void foo(void)
{
char *p = malloc(42);

if (!p)
return;

/*...*/

if (bad_condition) {
free(p);
return;
}

if (new_bad_condition) {
return;
}

/*...*/

free(p);
return;
}

With multiple exit points, the cleanup code must be diligently
reproduced before each return. Forgetting but one leads to
an error. The larger the function and the more exit points
it has, the more error prone it is to maintain it (until it
becomes so large and error prone, that it's error prone-ness
becomes legendary and every programmer in the organization
treats it with caution!)

The problem exists because C doesn't have any way of specifying
a common block of cleanup code to be done when a function
terminates. The closest approximation is to replace the
return statements with goto statements that branch forward
to some cleanup code at the end of the function.


Richard Stamp

unread,
Jun 2, 1998, 3:00:00 AM6/2/98
to

In article <01bd8e63$7e650ca0$cc4e...@grouper.iaehv.nl>,

TPJ <to...@iaehv.nl.NOSPAM> wrote:
>Hi All,
> I recently came across a C coding guideline stating
>that every function should have a single exit point (Or in other
>words, avoid multiple 'return' stmts). Me and my friends are a

>bit divided on supporting/not supporting this guideline.

I tend to agree that a single exit point is a good move, not because of any
argument over "elegance", but simply because it allows you to concentrate
in one place all the cleaning-up and generally housekeeping you need to do
before exiting the function. Admittedly, not all functions do things
(allocate memory, open files) which need to be reversed in that way -- but
consistency is good too, so if you're going to rule that certain functions
should have a single exit point it would seem to follow that *all* should
have a single return.

The question arises, though, of how you implement that. For example,
suppose an unusual "error" condition forces you to abandon the function
part way through. One possibility is an arrangement like

if (x = malloc (42)) {
if ((f = fopen("foobar","r")) {
/* ... etc. etc. etc. */
fclose (f);
}
free (x);
}

but I've never been a great fan of that: I've somehow always had the
intuitive notion that an "if" should enclose the uncommon, or
short-to-deal-with, or generally subsidiary case. Packaging up the
"normal" behaviour inside an "if" just looks wrong to me.

The trouble with this line of argument is that it leads inexorably
towards an (ack!) goto...

x = malloc (42);
if (!x) goto bail_out;
/* ... */
bail_out: return;

...and of course, we all "know" that goto is a "bad thing". On the other
hand, the method of dealing with an exceptional condition in more modern
languages is to raise an exception -- which is really just a goto
travelling incognito -- and nobody seems to object to that. Maybe the
acceptance comes from the fact that the jump is performed for a well-known
purpose, and therefore kept somehow "under control".

I don't think there is an ideal solution. Adding extra structure (more
if's) to deal with unusual cases obscures the "normal" function of the
code, while adding jumps (gotos, breaks, premature returns) disrupts
the familiar flow. Personally I'd favour a single exit point with a
balance of structured constructs to deal with "usual" cases and jumps
to handle truly exceptional errors.

These are contentious issues; the above is mere opinion.

Cheers,
Richard
--
Richard Stamp
Churchill College, Cambridge

Jack Klein

unread,
Jun 3, 1998, 3:00:00 AM6/3/98
to

TPJ <to...@iaehv.nl.NOSPAM> wrote in article
<01bd8e63$7e650ca0$cc4e...@grouper.iaehv.nl>...

> Hi All,
> I recently came across a C coding guideline stating
> that every function should have a single exit point (Or in other
> words, avoid multiple 'return' stmts). Me and my friends are a
> bit divided on supporting/not supporting this guideline. The
> supporting argument for this guideline is that using multiple
> returns is not structured programming and it should be avoided
> at least in cases where the function returns a value.
>
> I would be very grateful if somebody could relate their opinions/
> experiences for or against this guideline. Any relevant input would
> be welcome.
> Thanks for Ur time and patience,
> With best regards,
> TPJ
>

<Jack>

Some responses indicate that achieving a single return in a function
almost involves many nested if statements or goto statements.

I find a single nested do { } while (0) block often suffices, although
it might require some extra initialization of variables:

int func(/* args */)
{
FILE *f = NULL;
char *c = NULL;
int return_val = RETURN_OK;
do
{
if ((c = malloc(...)) == NULL)
{
return_val = MEM_ERROR;
break;
}

if ((f = fopen(...)) == NULL)
{
return_val = FILE_NOT_FOUND;
break;
}

/* and so on */
} while (0);
/* clean up */
if (f) fclose(f);
if (c) free(c); /* could be free'd regardless */
return return_val;
}

This is another way of using multiple goto's except that every single
one of them goes to exactly the same place, where the function's clean
up and termination are performed.

If you did use goto's instead, someone later reading or maintaining the
code would have to check if there were one or more target labels, and
see where each goto went to.

</Jack>


Jack Klein

unread,
Jun 3, 1998, 3:00:00 AM6/3/98
to

Gary Yngve <ga...@angband.org> wrote in article
<6l1ufh$lpc$1...@news-int.gatech.edu>...
> TPJ <to...@iaehv.nl.NOSPAM> wrote:
> : Hi All,

> : I recently came across a C coding guideline stating
> : that every function should have a single exit point (Or in other
> : words, avoid multiple 'return' stmts). Me and my friends are a
> : bit divided on supporting/not supporting this guideline. The
> : supporting argument for this guideline is that using multiple
> : returns is not structured programming and it should be avoided
> : at least in cases where the function returns a value.
>
> By having a return value at the end of a function and nowhere else,
it
> guarrantees that the function will always return, as opposed to
having
> returns inside different if/else if blocks or something.
>
> It generally eases debugging - nothing is more annoying than to track
down
> a bug when a function ends but doesn't return but is supposed to.

How can a function end without returning? Are you talking about C or
some other language?

> For that matter, if a function wasn't prototyped and assumes to
return
> another type, bad things could happen as well. I've seen weird stuff
happen
> on an x86 where the function was supposed to return float but the
compiler
> assumed int and as a result the floating point stack overflowed.

For that matter, if a function wasn't prototyped and the programmer
claimed to be a professional and was being paid for the work, he should
be either trained properly or dismissed. Set the warning level
appropriately on the compiler.

> The other day I was careless and left a return off the end of a
function.
> Not bothering to lint my code, I ran it. It worked fine on my Linux
box,
> probably because the program was grabbing the return value off of AX
which
> already held it. But then when I ran it on an SGI, it didn't work at
all.

Again, set the warning levels appropriately on the compiler. The tools
will call such simple mistakes to your attention immediately.

> --
> And the number one reason why David Korn is cool:
> main() {
printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
>
> ||| Gary Yngve ||| |||
ga...@cc.gatech.edu |||
>

Gary Yngve

unread,
Jun 3, 1998, 3:00:00 AM6/3/98
to

Jack Klein <jack...@worldnet.att.net> wrote:
: Gary Yngve <ga...@angband.org> wrote in article
: <6l1ufh$lpc$1...@news-int.gatech.edu>...
:> By having a return value at the end of a function and nowhere else,

: it
:> guarrantees that the function will always return, as opposed to
: having
:> returns inside different if/else if blocks or something.
:>
:> It generally eases debugging - nothing is more annoying than to track
: down
:> a bug when a function ends but doesn't return but is supposed to.

: How can a function end without returning? Are you talking about C or
: some other language?

return, as opposed to fallthrough. explicitly use the keyword "return."

<some stuff cut on the praises of using stricter warnings>

yeah, I was just hacking out some code and didn't bother. Once I noticed
an error, the warnings made it trivial to track the error.

For that matter, there was a weirder error - I was using drand48(), and
when I used "-ansi", drand48() was not being prototyped, despite being
in stdlib.h.

Szu-Wen Huang

unread,
Jun 3, 1998, 3:00:00 AM6/3/98
to

TPJ (to...@iaehv.nl.NOSPAM) wrote:
[...]

: I recently came across a C coding guideline stating
: that every function should have a single exit point (Or in other
: words, avoid multiple 'return' stmts). Me and my friends are a
: bit divided on supporting/not supporting this guideline. The
: supporting argument for this guideline is that using multiple
: returns is not structured programming and it should be avoided
: at least in cases where the function returns a value.

Well, a good test is to actually write sample code that break the
rule. Compare:

if (x > 0)
return 1;
else
return 0;

to:

return (x > 0);

Neither is obviously significantly superior to the other in terms
of readability. In fact, the second one requires that you know
boolean operators return 1 or 0, so it actually takes more knowledge
to understand.

Another example might be:

if (possible_error_1)
{
/* handle error 1 */
return BAD;
}
if (possible_error_2)
{
/* handle error 2 */
return BAD;
}
/* process */
return GOOD;

which uses three returns, and yet cannot be said to be unclear.

On the other hand, a function with more than a few returns, just
like one with more than a few breaks, continues, or gotos, is likely
to be confusing to read. Humans like to read from the top to the
bottom without skipping around.

Therefore, rules are good, because they point out potential problem
areas. Even if you don't strictly follow this single exit point
rule, the sensible programmer realizes what it's *meant* to prevent.
This particular rule sounds like an exaggeration of a good programming
principle.

Dan Pop

unread,
Jun 3, 1998, 3:00:00 AM6/3/98
to

In <01bd8e63$7e650ca0$cc4e...@grouper.iaehv.nl> "TPJ" <to...@iaehv.nl.NOSPAM> writes:

> I recently came across a C coding guideline stating
>that every function should have a single exit point (Or in other
>words, avoid multiple 'return' stmts).

Didn't they also recommend the following macros:

#define BEGIN {
#define END }

:-)

Any C coding guideline forcing extra levels of indentation (because of
additional control structures) or extra goto's is a bad thing.

Having a single exit point is nice, *if* it can be achieved without
compromising the overall structure of the code. In most cases, it
cannot. The top two priorities when writing code are:

1. To get it right.

2. To get it easy to read and understand.

Dan
--
Dan Pop
CERN, IT Division
Email: Dan...@cern.ch
Mail: CERN - PPE, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland

gste...@sprynet.com

unread,
Jun 3, 1998, 3:00:00 AM6/3/98
to

Hmmm. I've been coding in C since 1988. In college,(Brooklyn Polytechnic) I
was instructed not to use multiple return statements in a function, and not to
use gotos. Those were 2 of the rules of structured programming spoken unto me.
I have followed them, without exception, in all the code that I have written.
Well, maybe some test code had multiple returns, but NEVER gotos.

-GS

In article <01bd8e63$7e650ca0$cc4e...@grouper.iaehv.nl>,


"TPJ" <to...@iaehv.nl.NOSPAM> wrote:
>
> Hi All,

> I recently came across a C coding guideline stating
> that every function should have a single exit point (Or in other

> words, avoid multiple 'return' stmts). Me and my friends are a
> bit divided on supporting/not supporting this guideline. The
> supporting argument for this guideline is that using multiple
> returns is not structured programming and it should be avoided
> at least in cases where the function returns a value.
>

> I would be very grateful if somebody could relate their opinions/
> experiences for or against this guideline. Any relevant input would
> be welcome.
> Thanks for Ur time and patience,
> With best regards,
> TPJ
>

> --
> Please remove the 'NOSPAM' from my Email ID
> to reply to this message.
>


-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/ Now offering spam-free web-based newsreading

Craig Franck

unread,
Jun 3, 1998, 3:00:00 AM6/3/98
to

Gary Yngve <ga...@angband.org> wrote:

>For that matter, there was a weirder error - I was using drand48(), and
>when I used "-ansi", drand48() was not being prototyped, despite being
>in stdlib.h.

That's normal; drand48() isn't a standard library function. There is
a macro you can test to see if the compiler is in standard C mode.
You normally would use it as such:

#if !__STDC__

/* nonstandard stuff */

#endif

When the compiler is in ANSI C mode, you don't want to include non-
standard things in a standard header. That's why the prototype for
drand48() went away when the -ansi switch was used. Implementors
often use this to expand the standard library.

You may also see:

#ifdef __cplusplus
extern "C" {
#endif

The __cplusplus macro is defined by all C++ compilers. This allows
you to use the same headers in C or C++ mode. (I'm not sure if this
scheme had to be expanded upon under the new C++ standard.)

--
Craig
clfr...@worldnet.att.net
Manchester, NH
If you have enough spiritual power to levitate a car, what
difference does it make what religion you call yourself?
-- "Stella"


Szu-Wen Huang

unread,
Jun 3, 1998, 3:00:00 AM6/3/98
to

Gary Yngve (ga...@angband.org) wrote:
[...]
: <some stuff cut on the praises of using stricter warnings>

: yeah, I was just hacking out some code and didn't bother. Once I noticed
: an error, the warnings made it trivial to track the error.

And turning them on in the first place would've saved you even more
time. A lot of bad things have been done in the name of "this is just
a quick hack". In this particular case, what if you didn't notice an
error? Your Linux machine, IIRC, certainly didn't.

: For that matter, there was a weirder error - I was using drand48(), and

: when I used "-ansi", drand48() was not being prototyped, despite being
: in stdlib.h.

drand48() isn't ANSI, so stdlib.h is perfectly correct for not polluting
your namespace with this identifier when you specify ANSI to your
compiler.

Kaz Kylheku

unread,
Jun 3, 1998, 3:00:00 AM6/3/98
to

On Wed, 03 Jun 1998 16:14:20 GMT, gste...@sprynet.com wrote:

>Hmmm. I've been coding in C since 1988. In college,(Brooklyn Polytechnic) I
>was instructed not to use multiple return statements in a function, and not to
>use gotos. Those were 2 of the rules of structured programming spoken unto me.

And of course, these rules conflict! Because to avoid multiple returns from
the function, sometimes the best thing is a forward goto.


sylv...@mypc.microtec.net

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

On 3 Jun 1998 13:33:00 GMT, hu...@mnsinc.com (Szu-Wen Huang) wrote:

>TPJ (to...@iaehv.nl.NOSPAM) wrote:
>[...]
>: I recently came across a C coding guideline stating


>: that every function should have a single exit point (Or in other
>: words, avoid multiple 'return' stmts). Me and my friends are a
>: bit divided on supporting/not supporting this guideline. The
>: supporting argument for this guideline is that using multiple
>: returns is not structured programming and it should be avoided
>: at least in cases where the function returns a value.
>

>Well, a good test is to actually write sample code that break the
>rule. Compare:
>
> if (x > 0)
> return 1;
> else
> return 0;
>
>to:
>
> return (x > 0);
>
>Neither is obviously significantly superior to the other in terms
>of readability. In fact, the second one requires that you know
>boolean operators return 1 or 0, so it actually takes more knowledge
>to understand.
>

Isn't knowing that boolean operators return 1 or 0, a basic part of
knowing C ?

I always check what a language returns for true and false statements.


--
Sylvain Poirier
sylv...@mypc.microtec.net (remove mypc. for reply)
___
C is mother, C is father.

Bruce

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

In comp.lang.c
Dan...@cern.ch (Dan Pop) wrote:

>Any C coding guideline forcing extra levels of indentation (because of
>additional control structures) or extra goto's is a bad thing.
>
>Having a single exit point is nice, *if* it can be achieved without
>compromising the overall structure of the code. In most cases, it
>cannot. The top two priorities when writing code are:
>
>1. To get it right.
>
>2. To get it easy to read and understand.

Finally someone that agrees with me on this and
I'm glad to see it is someone who's knowledge I
respect. Welcome back Dan.


Bruce D. Wedding
Scientific MicroSystems, Inc.
http://www.scimisys.com
Tomball, Texas

Michel Bardiaux

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

What about:

#define RETURN goto cleanup

--
Michel Bardiaux
UsrConsult S.P.R.L. Rue Margot, 37 B-1457 Nil St Vincent
Tel : +32 10 65.44.15 Fax : +32 10 65.44.10

gste...@sprynet.com

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

In article <35759d29....@207.126.101.81>,

k...@cafe.net wrote:
>
> On Wed, 03 Jun 1998 16:14:20 GMT, gste...@sprynet.com wrote:
>
> >Hmmm. I've been coding in C since 1988. In college,(Brooklyn Polytechnic) I
> >was instructed not to use multiple return statements in a function, and not
to
> >use gotos. Those were 2 of the rules of structured programming spoken unto
me.
>
> And of course, these rules conflict! Because to avoid multiple returns from
> the function, sometimes the best thing is a forward goto.
>
>

I see no conflict. I firmly beleive that there is no program segment that
cannot be written without a goto.

Chris Engebretson

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

In article <6l65bi$tag$1...@nnrp1.dejanews.com>, gste...@sprynet.com writes:

|> I see no conflict. I firmly beleive that there is no program
|> segment that cannot be written without a goto.

This is true, and can be proven as such.

However, you might also say that there is no location in the
continental United States that cannot be reached on foot. This,
for all practical purposes, is also true. However, I don't know
many people who walk to work.

One needs to differentiate between "bad" and "good" uses of goto:

1. Using a goto when a perfectly legitimate and existing structured
technique will work without adding needless complexity.

2. Using a goto as a "last resort" to avoid turning an otherwise
straightforward function into a byzantine labyrinth of control
structures, nested loops, and conditional tests.

The extremists will tell you that neither of these is a legitimate
justification for using a goto. Instead, they would have you
believe that re-writing code that uses goto (no matter the purpose),
possibly ballooning it up to twice its normal size simply to remove
that dreaded eyesore, is a noble and heroic gesture. They say the
same thing about multiple exit points. They preach that pristine,
unadulterated structure is absolute, and compromises are
entirely unacceptable.

This certainly looks good on paper. But from where I stand,
nobility and heroism are out, and common sense is in. One needs
not use goto to write spaghetti code.

Regards,

--
Chris Engebretson - Raytheon STX Corporation | Ph#: (605)594-6829
USGS EROS Data Center, Sioux Falls, SD 57198 | Fax: (605)594-6940
http://edcwww.cr.usgs.gov/ mailto:enge...@sg1.cr.usgs.gov
Opinions are not those of Raytheon Systems Company or the USGS.

Jens Schweikhardt

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

gste...@sprynet.com wrote:
# In article <35759d29....@207.126.101.81>,
# k...@cafe.net wrote:
#>
#> On Wed, 03 Jun 1998 16:14:20 GMT, gste...@sprynet.com wrote:
#>
#> >Hmmm. I've been coding in C since 1988. In college,(Brooklyn Polytechnic) I
#> >was instructed not to use multiple return statements in a function, and not
# to
#> >use gotos. Those were 2 of the rules of structured programming spoken unto
# me.
#>
#> And of course, these rules conflict! Because to avoid multiple returns from
#> the function, sometimes the best thing is a forward goto.

# I see no conflict. I firmly beleive that there is no program segment that
# cannot be written without a goto.

In theory, yes. But is is practical? No. Please write the tcp_input
function (which you find in any decent OS source code) without goto and
keep it readable. Then I will believe the 'no goto' camp. Not one second
earlier.

Let the flame fest begin.

Regards,

Jens
--
Jens Schweikhardt http://www.shuttle.de/schweikh
SIGSIG -- signature too long (core dumped)

Billy Chambless

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

In article <6l6c0k$o8k$3...@news.BelWue.DE>, Jens Schweikhardt <schw...@diamant.noc.dfn.de> writes:
|> gste...@sprynet.com wrote:

|> # I see no conflict. I firmly beleive that there is no program segment that
|> # cannot be written without a goto.

|> In theory, yes. But is is practical? No. Please write the tcp_input
|> function (which you find in any decent OS source code) without goto and
|> keep it readable. Then I will believe the 'no goto' camp. Not one second
|> earlier.

I find the "no goto" thing interesting.

The arguments seem to boil down to:

1. Misuse of gotos can lead to hard to read code.
2. Any section of code can be rewritten without gotos.

I submit that the above two statements are just as true of:

the do { ... } while construct
the ternary logical operator
while() loops ( after all, they can be replaced with for() loops )
for() loops ( after all, they can be replaced with while() loops )
preprocessor #defines
pointers

For any given X, the fact that X can be used stupidly is not a reason
to avoid using X wisely.

Craig Franck

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

That's about what it boils down to. The thing I dislike most about
ruling out all goto use is it's used as a replacement for actual
thought. A teacher figures by ruling them out completely you will
eliminate a lot of foolish code by students who lack the knowledge
to discriminate. But by doing this, they never make mistakes and
see what's good and what's bad (other than being shown some
ridiculously bad examples). It's almost like telling a kid to always
take his shoes off when they come inside because they can't be
trusted to use good judgment about not tracking the floor up with
mud.

cafe.net

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

In article <6l65bi$tag$1...@nnrp1.dejanews.com>, <gste...@sprynet.com> wrote:
>
>I see no conflict. I firmly beleive that there is no program segment that
>cannot be written without a goto.

The rules conflict because when you try to satisfy them simultaneously,
you may come up with a function that is less readable and maintainable
than if you ignore one of the two rules. But the whole point motivation
a coding standard is to produce readable and maintainable code.
That is why I say that the rules conflict.

Dann Corbit

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

Craig Franck wrote in message <6l6lak$3...@bgtnsc03.worldnet.att.net>...
[snip]

>That's about what it boils down to. The thing I dislike most about
>ruling out all goto use is it's used as a replacement for actual
>thought. A teacher figures by ruling them out completely you will
>eliminate a lot of foolish code by students who lack the knowledge
>to discriminate. But by doing this, they never make mistakes and
>see what's good and what's bad (other than being shown some
>ridiculously bad examples). It's almost like telling a kid to always
>take his shoes off when they come inside because they can't be
>trusted to use good judgment about not tracking the floor up with
>mud.

I would differentiate between teaching and using. When I taught C, I told
students that they were not allowed to turn in any code with goto's or
multiple returns. Period. Any assignment with either construct would be
returned for restructuring. I said that in real life, you can use them when
you want them. That is because many students had experience in "old style"
COBOL or FORTRAN programming and unless you forced the issue you would get
spaghetti. Also, there are a few new programmers who only have experience
in Assembly language - again laced with goto. I think it is an excellent
exercise to force people to think of alternatives. Often, even in "real
code" by "real programmers," goto's and the like are just the result of lazy
thinking. If they learn to consider the alternatives when they are just
starting out, they will consider the alternatives in practice. Or at least,
they are more likely to.
--
Hypertext C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-FAQ ftp: ftp://rtfm.mit.edu, C-FAQ Book: ISBN 0-201-84519-9
Try "C Programming: A Modern Approach" ISBN 0-393-96945-2
Want Software? Algorithms? Pubs? http://www.infoseek.com

gste...@sprynet.com

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

I write BSPs for custom hardware without an OS. Provide me with this tcp_input
function and Ill give it a try.

In article <6l6c0k$o8k$3...@news.BelWue.DE>,


Jens Schweikhardt <schw...@diamant.noc.dfn.de> wrote:
>
> gste...@sprynet.com wrote:
> # In article <35759d29....@207.126.101.81>,
> # k...@cafe.net wrote:
> #>
> #> On Wed, 03 Jun 1998 16:14:20 GMT, gste...@sprynet.com wrote:
> #>
> #> >Hmmm. I've been coding in C since 1988. In college,(Brooklyn
Polytechnic) I
> #> >was instructed not to use multiple return statements in a function, and
not
> # to
> #> >use gotos. Those were 2 of the rules of structured programming spoken
unto
> # me.
> #>
> #> And of course, these rules conflict! Because to avoid multiple returns
from
> #> the function, sometimes the best thing is a forward goto.
>

> # I see no conflict. I firmly beleive that there is no program segment that
> # cannot be written without a goto.
>
> In theory, yes. But is is practical? No. Please write the tcp_input
> function (which you find in any decent OS source code) without goto and
> keep it readable. Then I will believe the 'no goto' camp. Not one second
> earlier.
>

> Let the flame fest begin.
>
> Regards,
>
> Jens
> --
> Jens Schweikhardt http://www.shuttle.de/schweikh
> SIGSIG -- signature too long (core dumped)
>

firewind

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

On Thu, 4 Jun 1998, Michel Bardiaux wrote:

> What about:
>
> #define RETURN goto cleanup

A goto by any other name would smell as sweet. (Or as bad, depending on your
particular religious beliefs.)

--
(initiator of the campaign for grumpiness where grumpiness is due in c.l.c)

Attempting to write in a hybrid which can be compiled by either a C compiler
or a C++ compiler produces a compromise language which combines the drawbacks
of both with the advantages of neither.
-- John Winters <jo...@polo.demon.co.uk> in comp.lang.c


firewind

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

On Thu, 4 Jun 1998 gste...@sprynet.com wrote:

> I see no conflict. I firmly beleive that there is no program segment that

> cannot be written without a goto.

Indeed, you are correct. However, -I- firmly believe that there -are- program
segments in which the non-'goto' using solution is uglier, less maintainable,
and less structured than the 'goto' using solution.

Szu-Wen Huang

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

gste...@sprynet.com wrote:
: Hmmm. I've been coding in C since 1988. In college,(Brooklyn Polytechnic) I
: was instructed not to use multiple return statements in a function, and not to
: use gotos. Those were 2 of the rules of structured programming spoken unto me.

: I have followed them, without exception, in all the code that I have written.
: Well, maybe some test code had multiple returns, but NEVER gotos.

Ever written a comparison function for qsort()? You'll need to return
a negative number, zero, or a positive number. Trying to return 3 (or
more) possible values in one single statement will probably make your
code less readable, not more.

That doesn't mean almost randomly sprinkled return statements are good,
naturally.

Kaz Kylheku

unread,
Jun 4, 1998, 3:00:00 AM6/4/98
to

In article <6l6ut2$6t7$1...@nnrp1.dejanews.com>, <gste...@sprynet.com> wrote:
>I write BSPs for custom hardware without an OS. Provide me with this tcp_input
>function and Ill give it a try.

www.kernel.org

Jens Schweikhardt

unread,
Jun 5, 1998, 3:00:00 AM6/5/98
to

gste...@sprynet.com wrote:
# I write BSPs for custom hardware without an OS. Provide me with this tcp_input
# function and Ill give it a try.

[goto discussion]

#> In theory, yes. But is is practical? No. Please write the tcp_input
#> function (which you find in any decent OS source code) without goto and
#> keep it readable. Then I will believe the 'no goto' camp. Not one second
#> earlier.

Just ask http://ftpsearch.ntnu.no/ for tcp_input.c and pick the nearest
site. I suggest you use one from the BSD sources. I do not post it here
because it might be considered off-topic and, what's more, tcp_input is
> 40Kbyte in size. One reason it uses gotos is that the RFC describing
tcp protocol specification can then be followed by the letter.

Let me know if you succeed :-)

Regards, (Posted and mailed)

Szu-Wen Huang

unread,
Jun 8, 1998, 3:00:00 AM6/8/98
to

sylv...@mypc.microtec.net wrote:
: On 3 Jun 1998 13:33:00 GMT, hu...@mnsinc.com (Szu-Wen Huang) wrote:
[...]
: >Neither is obviously significantly superior to the other in terms

: >of readability. In fact, the second one requires that you know
: >boolean operators return 1 or 0, so it actually takes more knowledge
: >to understand.

: Isn't knowing that boolean operators return 1 or 0, a basic part of
: knowing C ?

It is, but you shouldn't be too surprised if you find that a lot of
C programmers don't know that it's defined/guaranteed by the language.

: I always check what a language returns for true and false statements.

And you are correct to do so. However, we need to keep in mind that
maintenance programmers tend to be the least experienced of the lot,
and if they don't understand your code, it doesn't matter if it's
bug-free because *they'll* break it trying to "fix" your code.

I say use as many returns as necessary to achieve a clear program.
The number is probably small, but not always one.

Szu-Wen Huang

unread,
Jun 8, 1998, 3:00:00 AM6/8/98
to

gste...@sprynet.com wrote:
: In article <35759d29....@207.126.101.81>,
: k...@cafe.net wrote:
[...]
: > And of course, these rules conflict! Because to avoid multiple returns
: > from the function, sometimes the best thing is a forward goto.

: I see no conflict. I firmly beleive that there is no program segment that


: cannot be written without a goto.

Yes, but is a program that avoids goto necessarily better than the one
that doesn't?

A programmer (to paraphrase something I read here but can no longer
attribute) writes code in order to communicate to two equally important
entities:

1. the compiler(s)
2. the maintenance programmer(s)

Target number one doesn't care if you use gotos or multiple returns.
Target number two requires we write the clearest possible code, and
multiply-nested code is not necessarily clearer than one or two
gotos. The *goal* of programming is not to avoid gotos and multiple
returns, but to write good (which most of the time means clear) code.

Larry Weiss

unread,
Jun 8, 1998, 3:00:00 AM6/8/98
to

Dan Pop wrote:
> Any C coding guideline forcing extra levels of indentation (because
> of additional control structures) or extra goto's is a bad thing.
> Having a single exit point is nice, *if* it can be achieved without
> compromising the overall structure of the code. In most cases, it
> cannot. The top two priorities when writing code are:
> 1. To get it right.
> 2. To get it easy to read and understand.
>

It's frustrating to find some code that could have been written
with a simple return statement embedded in the middle of a function,
but unfortunately was written with some inadequately implemented
yet ornate control structure whose only purpose was to allow a
single point of return from the extreme lexical end of that function.

The solution was at hand, but never grasped...

- Larry Weiss

Larry Weiss

unread,
Jun 8, 1998, 3:00:00 AM6/8/98
to

Michel Bardiaux wrote:

> Kaz Kylheku wrote:
> > And of course, these rules conflict! Because to avoid multiple
> > returns from the function, sometimes the best thing is a
> > forward goto.
>
> What about:
>
> #define RETURN goto cleanup
>

Seems moderately obfuscational to me...

- Larry Weiss

Larry Weiss

unread,
Jun 8, 1998, 3:00:00 AM6/8/98
to

firewind wrote:
> Indeed, you are correct. However, -I- firmly believe that there
> -are- program segments in which the non-'goto' using solution is
> uglier, less maintainable, and less structured than the 'goto'
> using solution.
>

What's faith have to do with this question? Is it not possible
to exhibit such a solution?

- Larry Weiss

Cathy or John

unread,
Jun 9, 1998, 3:00:00 AM6/9/98
to

In article <6lhlhg$h...@espresso.cafe.net>, k...@cafe.net wrote:

> In article
<DF9360A68416208E.1FE768BC...@library-proxy.airnews.net>,

> Sure:
>
> #include <stddef.h>
>
> struct foo { /*...*/ };
>
> void foo_init(struct foo *);
>
> struct foo *foo_alloc_init(void)
> {
> struct foo *f = malloc(sizeof *f);
>
> if (!f)
> goto foo_alloc_failed;
>
> if ((f->r1 = alloc_resource_1()) == NULL)
> goto foo_alloc_r1_failed;
>
> if ((f->r2 = alloc_resource_2()) == NULL)
> goto foo_alloc_r2_failed;
>
> if ((f->r3 = alloc_resource_3()) == NULL)
> goto foo_alloc_r3_failed;
>
> if ((f->r4 = alloc_resource_4()) == NULL)
> goto foo_alloc_r4_failed;
>
> if ((f->r5 = alloc_resource_5()) == NULL)
> goto foo_alloc_r5_failed;
>
> foo_init(f);
> return f;
>
> foo_alloc_r5_failed:
> free_resource_r4(f->r4);
> foo_alloc_r4_failed:
> free_resource_r3(f->r3);
> foo_alloc_r3_failed:
> free_resource_r2(f->r2);
> foo_alloc_r2_failed:
> free_resource_r1(f->r1);
> foo_alloc_r1_failed:
> free(f);
> foo_alloc_failed:
> return NULL;
> }
>
> I'd hate to write (or read) the nested if version of that.
>
> Give me exception handling, or give me goto. :)

#include <stddef.h>

struct foo { /*...*/ };

void foo_init(struct foo *);

struct foo *foo_alloc_init(void)
{
struct foo *f = malloc(sizeof *f);

if (!f)
else if ((f->r1 = alloc_resource_1()) == NULL) {
free(f);
return NULL;
}
else if ((f->r2 = alloc_resource_2()) == NULL) {
free_resource_r1(f->r1);
free(f);
}
else if ((f->r3 = alloc_resource_3()) == NULL) {
free_resource_r2(f->r2);
free_resource_r1(f->f1);
free(f);
}
else if ((f->r4 = alloc_resource_4()) == NULL) {
free_resource_r3(f->r3);
free_resource_r2(f->r2);
free_resource_r1(f->r1);
free(f);
}
else if ((f->r5 = alloc_resource_5()) == NULL) {
free_resource_r4(f->r4);
free_resource_r3(f->r3);
free_resource_r2(f->r2);
free_resource_r1(f->r1);
free(f)
}
else { /* There are no errors, return okay */
foo_init(f);
return f;
}

return NULL; /* Return NULL, this didn't work */
}

Does this work? It isn't that bad, especially once you start adding
comments to explain what exactly the errors are that you're testing for.

--John
jc6...@acs.brockport.edu

Lawrence Kirby

unread,
Jun 9, 1998, 3:00:00 AM6/9/98
to

In article <6lhlhg$h...@espresso.cafe.net> k...@cafe.net "Kaz Kylheku" writes:

>In article <DF9360A68416208E.1FE768BC7231257F.43CF
>DFA283...@library-proxy.airnews.net>,


>Larry Weiss <l...@airmail.net> wrote:
>>firewind wrote:
>>> Indeed, you are correct. However, -I- firmly believe that there
>>> -are- program segments in which the non-'goto' using solution is
>>> uglier, less maintainable, and less structured than the 'goto'
>>> using solution.
>>>
>>
>>What's faith have to do with this question? Is it not possible
>>to exhibit such a solution?
>
>Sure:
>

...

>I'd hate to write (or read) the nested if version of that.
>
>Give me exception handling, or give me goto. :)

I think I'd prefer something along the lines of what I posted in the
``Dynamic 3D Array'' thread. IMO it simplified things overall to have a
generic cleanup function.

--
-----------------------------------------
Lawrence Kirby | fr...@genesis.demon.co.uk
Wilts, England | 7073...@compuserve.com
-----------------------------------------


Homer Meyer

unread,
Jun 9, 1998, 3:00:00 AM6/9/98
to

Actually, I think both of the solutions presented so far are ugly. Here's
another solution. This relies on the fact that all of the
alloc_resource_x() functions return NULL on error and that free() simply
returns when passed a NULL value. To me this is cleaner than both of the
previous solutions.

#include <stddef.h>

struct foo { /*...*/ };

void foo_init(struct foo *);

struct foo *foo_alloc_init(void)
{
struct foo *f = malloc(sizeof *f);

if( f )
{
f->r1 = alloc_resource_1();
f->r2 = alloc_resource_2();
f->r3 = alloc_resource_3();
f->r4 = alloc_resource_4();
f->r5 = alloc_resource_5();
}

if( f && f->r1 && f->r2 && f->r3 && f->r4 && f->r5 )
{
foo_init(f);
return f;
}
else
{
/* allocation failed */
if( f )
{
free( f->r1 );
free( f->r2 );
free( f->r3 );
free( f->r4 );
free( f->r5 );
free( f );
}
return NULL;
}
}

Cathy or John wrote in message ...


>In article <6lhlhg$h...@espresso.cafe.net>, k...@cafe.net wrote:
>
>> In article
><DF9360A68416208E.1FE768BC...@library-proxy.airnews.n

et>,
>> Larry Weiss <l...@airmail.net> wrote:
>> >firewind wrote:
>> >> Indeed, you are correct. However, -I- firmly believe that there
>> >> -are- program segments in which the non-'goto' using solution is
>> >> uglier, less maintainable, and less structured than the 'goto'
>> >> using solution.
>> >>
>> >
>> >What's faith have to do with this question? Is it not possible
>> >to exhibit such a solution?
>>


<SNIP>

l...@airmail.net

unread,
Jun 9, 1998, 3:00:00 AM6/9/98
to

In article <6ljlbl$si9$1...@news-2.csn.net>,

"Homer Meyer" <ho...@cqgrd.com> wrote:
> Actually, I think both of the solutions presented so far are ugly. Here's
> another solution...

>
> #include <stddef.h>
> struct foo { /*...*/ };
> void foo_init(struct foo *);
> struct foo *foo_alloc_init(void)
> {
> struct foo *f = malloc(sizeof *f);
> if( f )
> {
> f->r1 = alloc_resource_1();
> f->r2 = alloc_resource_2();
> f->r3 = alloc_resource_3();
> f->r4 = alloc_resource_4();
> f->r5 = alloc_resource_5();
> }
> if( f && f->r1 && f->r2 && f->r3 && f->r4 && f->r5 )
> {
> foo_init(f);
> return f;
> }
> else
> {
> /* allocation failed */
> if( f )
> {
> free( f->r1 );
> free( f->r2 );
> free( f->r3 );
> free( f->r4 );
> free( f->r5 );
> free( f );
> }
> return NULL;
> }
> }
>

A little cleaner is this variation (IMO),
preserving your indentation style:

#include <stddef.h>
struct foo { /*...*/ };
void foo_init(struct foo *);
struct foo *foo_alloc_init(void)
{
struct foo *f = malloc(sizeof *f);

if( !f )
{
return NULL;
}
else
{
f->r1 = NULL;
f->r2 = NULL;
f->r3 = NULL;
f->r4 = NULL;
f->r5 = NULL;
if ( (f->r1 = alloc_resource_1())
&& (f->r2 = alloc_resource_2())
&& (f->r3 = alloc_resource_3())
&& (f->r4 = alloc_resource_4())
&& (f->r5 = alloc_resource_5()) )
{
foo_init(f);
return f;


}
}
free( f->r1 );
free( f->r2 );
free( f->r3 );
free( f->r4 );
free( f->r5 );
free( f );
return NULL;
}

- Larry Weiss

Lawrence Kirby

unread,
Jun 9, 1998, 3:00:00 AM6/9/98
to

In article <6ljlbl$si9$1...@news-2.csn.net> ho...@cqgrd.com "Homer Meyer" writes:

>Actually, I think both of the solutions presented so far are ugly. Here's

>another solution. This relies on the fact that all of the
>alloc_resource_x() functions return NULL on error and that free() simply
>returns when passed a NULL value. To me this is cleaner than both of the
>previous solutions.
>
>#include <stddef.h>

You need to include <stdlib.h> for malloc() and free(). You can then
probably omit <stddef.h>.

>struct foo { /*...*/ };
>
>void foo_init(struct foo *);
>
>struct foo *foo_alloc_init(void)
>{
>struct foo *f = malloc(sizeof *f);
>
>if( f )

You would simplfy the rest of the code if you used:

if (!f)
return NULL;

or nested the rest in this conditional.

>{
> f->r1 = alloc_resource_1();
> f->r2 = alloc_resource_2();
> f->r3 = alloc_resource_3();
> f->r4 = alloc_resource_4();
> f->r5 = alloc_resource_5();
>}


>
>if( f && f->r1 && f->r2 && f->r3 && f->r4 && f->r5 )
>{
> foo_init(f);
> return f;
>}
>else
>{
> /* allocation failed */
> if( f )
> {
> free( f->r1 );
> free( f->r2 );
> free( f->r3 );
> free( f->r4 );
> free( f->r5 );
> free( f );
> }
> return NULL;
>}
>}

You're probably still going to nee a dealloation function that can be
called by the code that called this function. You can use that here too.
I'd suggest something like:


#include <stdlib.h>

struct foo { /*...*/ };

struct foo *foo_alloc(void);
void foo_init(struct foo *);
void foo_free(struct foo *);


struct foo *foo_alloc(void)
{
struct foo *const f = malloc(sizeof *f);

if (f) {


f->r1 = alloc_resource_1();
f->r2 = alloc_resource_2();
f->r3 = alloc_resource_3();
f->r4 = alloc_resource_4();
f->r5 = alloc_resource_5();

if (f->r1 && f->r2 && f->r3 && f->r4 && f->r5) {
foo_init(f);
return f; /* SUCCESS */
}

foo_free(f);
}

return NULL;
}


void foo_free(struct foo *f)
{
if (f) {
free(f->r1);
free(f->r2);
free(f->r3);
free(f->r4);
free(f->r5);

free(f);

Ralph Silverman

unread,
Jun 10, 1998, 3:00:00 AM6/10/98
to

Will Rose (c...@cts.com) wrote:
: TPJ (to...@iaehv.nl.NOSPAM) wrote:
: : Hi All,
: : I recently came across a C coding guideline stating
: : that every function should have a single exit point (Or in other
: : words, avoid multiple 'return' stmts). Me and my friends are a
: : bit divided on supporting/not supporting this guideline. The
: : supporting argument for this guideline is that using multiple
: : returns is not structured programming and it should be avoided
: : at least in cases where the function returns a value.

: The answer is a definite maybe. Avoid multiple return points,
: yes, but sometimes they are handy. They may either form a
: useful abort on failure from multi-level conditional or loop
: code, or a quick return from the beginning of a function
: called with inappropriate parameters. I tend to avoid the
: first instance; my code usually returns either from the first
: line of a function (if the parameters are invalid) or the last.


: Will
: c...@crash.cts.com


subprogram ( function )
with multiple 'returns' ...

0) old question ...
languages before 'c' would
allow such potential ...
( ... also 'c' dates from
1970s ... ) ...

1) issue fundamentals ...
multiple 'returns'
allow more compact and faster
code ... in some circumstances
...
where speed and size are critical
... such may be preferable ...
however ...
code simplicity may be thought to
justify limit ( to one 'return' )
...
but ( when adequately justified )
code simplicity
also is compromised by 'work-arounds'
so ...
sometimes multiple returns
are reasonable
but, generally, should be used
only with great care ...
( general 'coding standard' rule
against such ... is
'lowest common denominator'
idea ... )

--

Ralph Silverman
z007...@bcfreenet.seflin.lib.fl.us


Homer Meyer

unread,
Jun 10, 1998, 3:00:00 AM6/10/98
to

Lawrence Kirby wrote in message <897435...@genesis.demon.co.uk>...

>In article <6ljlbl$si9$1...@news-2.csn.net> ho...@cqgrd.com "Homer Meyer"
writes:
>
>>Actually, I think both of the solutions presented so far are ugly. Here's
>>another solution. This relies on the fact that all of the
>>alloc_resource_x() functions return NULL on error and that free() simply
>>returns when passed a NULL value. To me this is cleaner than both of the
>>previous solutions.
>>
>>#include <stddef.h>
>
>You need to include <stdlib.h> for malloc() and free(). You can then
>probably omit <stddef.h>.


<SNIP>

I'm sure you're right. I just modified code previously posted here and as
this was just example code, I didn't change this.

>
>You're probably still going to nee a dealloation function that can be
>called by the code that called this function. You can use that here too.
>I'd suggest something like:
>


<SNIP>

In real code, sure you would. The original author posted this example to
show a case where goto's would be required to avoid more complex code. My
point was to show that it could be done without goto's, but also without the
complex conditionals and multiple deallocation sections. I think I made
that point.

rwil...@tuelectric.com

unread,
Jun 10, 1998, 3:00:00 AM6/10/98
to

If you're interested in what I think is the quintessential example of
multiple returns being the right way to code a particular program,
check out the following function which determines whether the
vertical line below a point crosses a line segment of a polygon.
(Counting the number of line segment crossings tells you whether
the point is inside or outside the polygon: odd=in, even=out.)

Bob Williamson

/******************************************************************************
FUNCTION NAME : short cross_line(double xf,
double yf,
NODE *this_v,
NODE *prev_v)
INPUTS : {xf,yf} (the XY-coordinate of the point) and pointers to
this & the previous line segments of the polygon linked list.
OUTPUT : short integer, value will be -2, -1, 0 or 1:
1 ==> x-projection crosses the line segment,
0 ==> x-projection does not cross the line segment,
-1 ==> point is on boundary; declared inside polygon,
-2 ==> point is on boundary; declared outside polygon.
Negative return values indicate that the point falls
directly on a polygon edge. The decision to return -1 or
-2 is somewhat arbitrarily based on the values of the XY-
coordinates of the polygon segment endpoints. Specifically,
if "this_v->x" > "next_v->x", "cross_line" returns -1 (i.e.,
{xf,yf} will be declared inside the polygon). If "this_v->x"
< "next_v->x", "cross_line" returns -2 (i.e., {xf,yf} will be
declared outside the polygon). If the X-coordinates are the
same (i.e., the polygon segment is vertical), then the Y-
values determine residency in the same way: "this_v" > "next_v"
returns -1, implying that the point is inside the polygon;
"this_v" < "next_v" returns -2. Thus, if all polygons are drawn
in a clockwise direction, the northern polygon (or in the case
of a vertical segment, the western polygon) of two adjacent
polygons would claim the residency of a point on the boundary
between the polygons. However, if the adjacent polygons are
drawn in opposite directions (one clockwise and the other
counter-clockwise) points on the common boundary could be
reported as residing in both or neither of the polygons. In
any case the number of facilities which will fall directly on
the boundary of a polygon is insignificant.
PURPOSE : Determines whether a line projected downward from the point
{xf,yf} crosses the line segment which is specified by the
structure referenced as the third argument of this function.
******************************************************************************/

struct Node { double x; /* X-coordinate of this vertex of polygon */
double y; /* Y-coordinate of this vertex of polygon */ double a; /*
Slope of line segment CW from {x,y} */ double b; /* Y-intrcpt of the
polygon line segment */ short c; /* Formula: 1==>y=ax+b; 0==>x=b;
-1==>x=ay+b */ struct Node *next_vrtx; }; typedef struct Node NODE;

short cross_line(double xf, double yf, NODE *this_v, NODE *prev_v)
{
double sa, xproj, yproj;
register NODE *next_v = this_v->next_vrtx;

if (!this_v->c) /* vertical polyg segmt */ { if (xf == this_v->x) /*
matching X-value */ { if (yf == this_v->y) /* matching Y-value */ { if
(this_v->y > next_v->y) /* North end of segment */ { if (this_v->x >
prev_v->x) return -2; else return -1; } else /* South end of segment */
{ if (this_v->y > prev_v->y) return -1; else return -2; } } else if (yf
> this_v->y) { if (yf > next_v->y) /* {xf,yf} above vertices */ { if
((xf > prev_v->x && xf < (next_v->next_vrtx)->x) || (xf < prev_v->x &&
xf > (next_v->next_vrtx)->x)) /* z-bend in polygon */ return 1; else
return 0; /* polyg is locally convex */ } else if (yf == next_v->y)
return 0; /* this->y < yf = next->y */ else return -2; /* this->y < yf
< next->y */ } else { if (yf < next_v->y) return 0; else return -1;
/* this_v->y > yf >next->y */ } } else return 0; } else /* segment
slope is finite */ { if (xf > this_v->x) { if (xf < next_v->x) { if
((yf > this_v->y) && (yf > next_v->y)) return 1; /* {xf,yf} is above box
*/ else if ((yf < this_v->y) && (yf < next_v->y)) return 0; /* {xf,yf} is
below box */ else { /* {xf,yf} is in box */ if (this_v->c > 0) /*
fabs(this_v->a) < 99.0 */ { /* Equation: y = a*x + b */ yproj =
(this_v->a) *xf + this_v->b; if (yf == yproj) return -2; /* {xf,yf} is on
boundary */ else if (yf>yproj) return 1; else return 0; } else /*
fabs(this_v->a) >= 99.0 */ { /* Equation: x = a*y + b */ xproj =
(this_v->a) * yf + this_v->b; if (xf == xproj) return -2; /* {xf,yf} is on
boundary */ sa = -(this_v->a); /* flips the axises of the */ if (sa*xf >
sa*xproj) /* over/under calculation */ return 1; else return 0; } }
} else return 0; } else if (xf < this_v->x) { if (xf > next_v->x) {
if ((yf > this_v->y) && (yf > next_v->y)) return 1; /* {xf,yf} is above
box */ else if ((yf < this_v->y) && (yf < next_v->y)) return 0; /*
{xf,yf} is below box */ else { /* {xf,yf} is in box */ if (this_v->c >
0) /* fabs(this_v->a) < 99.0 */ { /* Equation: y = a*x + b */ yproj =
(this_v->a)*xf+this_v->b; if (yf == yproj) return -1; /* this->x < xf <
next->x */ else if (yf>yproj) return 1; else return 0; } else { /*
Equation: x = a*y + b */ xproj = (this_v->a)*yf+this_v->b; if (xf ==
xproj) return -1; /* this->x < xf < next->x */ sa = -(this_v->a); /*
flips the axises of */ if (sa*xf > sa*xproj) /* over/under calculation */
return 1; else return 0; } } } else return 0; } else /*
projection thru vertex */ { if (yf > this_v->y) { if ((xf > prev_v->x &&
xf < next_v->x) || (xf < prev_v->x && xf > next_v->x)) return 1; else
return 0; } else if (yf < this_v->y) return 0; else /* {xf,yf} is this
vertex */ { if (this_v->x > next_v->x) { if (this_v->x < prev_v->x)
return -1; else if (this_v->x > prev_v->x) { if (this_v->a > 0.) return
-1; else return -2; } else { if (this_v->y > prev_v->y) return -1;
else return -2; } } else { if (this_v->x > prev_v->x) return -2; else
if (this_v->x < prev_v->x) { if (this_v->a > 0.) return -2; else return
-1; } else { if (this_v->y > prev_v->y) return -2; else return -1; }

Trevor R.H. Clarke

unread,
Jun 10, 1998, 3:00:00 AM6/10/98
to

In article <6lm8kf$h...@nntp.seflin.org>,

Ralph Silverman <z007...@bc.seflin.org> wrote:
>Will Rose (c...@cts.com) wrote:
>: TPJ (to...@iaehv.nl.NOSPAM) wrote:
>: : Hi All,
>: : I recently came across a C coding guideline stating
>: : that every function should have a single exit point (Or in other
>: : words, avoid multiple 'return' stmts). Me and my friends are a
>: : bit divided on supporting/not supporting this guideline. The
>: : supporting argument for this guideline is that using multiple
>: : returns is not structured programming and it should be avoided
>: : at least in cases where the function returns a value.
>
>: The answer is a definite maybe. Avoid multiple return points,
>: yes, but sometimes they are handy. They may either form a
>: useful abort on failure from multi-level conditional or loop
>: code, or a quick return from the beginning of a function
>: called with inappropriate parameters. I tend to avoid the
>: first instance; my code usually returns either from the first
>: line of a function (if the parameters are invalid) or the last.
>

My personal feeling is also a yes/no thing. I try to use one return per
function except for error processing. If I terminate because of an error, I
have no problem adding a new return. This way, I only have one "real" return
where a real return is a value used by the program instead on error or
diagnostic information. Example:

/* returns -1 on error or returns an integral value */

int foo(FILE *fp)
{
int a,b,c;

if(fscanf(fp,"%i %i",&a,&b) == EOF)
return -1; /* no input */

if(a >= b) {
if(b == 0)
return -1; /* divide by zero */
c = a / b;
} else {
if(a == 0)
return -1; /* divide by zero */
c = b / a;
}

return c; /* single "real" return.... */
}
--
Trevor R.H. Clarke http://www.csh.rit.edu/~retrev/
Computer Science House
Rochester Institute of Technology System Programmer for ISC
ret...@csh.rit.edu trc...@osfmail.isc.rit.edu

Lawrence Kirby

unread,
Jun 10, 1998, 3:00:00 AM6/10/98
to

In article <6lmmo7$9t2$1...@nnrp1.dejanews.com> rwil...@tuelectric.com writes:

>If you're interested in what I think is the quintessential example of
>multiple returns being the right way to code a particular program,
>check out the following function which determines whether the
>vertical line below a point crosses a line segment of a polygon.
>(Counting the number of line segment crossings tells you whether
>the point is inside or outside the polygon: odd=in, even=out.)

Maybe something went wrong with the formatting when you posted it. At any rate
as it stands describing it as the right way to do anything is a bit much! :-)

...

> if (!this_v->c) /* vertical polyg segmt */ { if (xf == this_v->x) /*
>matching X-value */ { if (yf == this_v->y) /* matching Y-value */ { if
>(this_v->y > next_v->y) /* North end of segment */ { if (this_v->x >
>prev_v->x) return -2; else return -1; } else /* South end of segment */
>{ if (this_v->y > prev_v->y) return -1; else return -2; } } else if (yf

...

Lawrence Kirby

unread,
Jun 10, 1998, 3:00:00 AM6/10/98
to

In article <6lmigl$oha$1...@news-2.csn.net> ho...@cqgrd.com "Homer Meyer" writes:

...

>In real code, sure you would. The original author posted this example to
>show a case where goto's would be required to avoid more complex code. My
>point was to show that it could be done without goto's, but also without the
>complex conditionals and multiple deallocation sections. I think I made
>that point.

No argument there. I'm just pointing out how it can be developed into
something more practical and useful (which just makes the argument for
it stronger).

Aaron Crane

unread,
Jun 10, 1998, 3:00:00 AM6/10/98
to

In article <6lmmo7$9t2$1...@nnrp1.dejanews.com>,

rwil...@tuelectric.com writes:
> If you're interested in what I think is the quintessential example of
> multiple returns being the right way to code a particular program,

Actually, this strikes me as the quintessential example of clear and
consistent indentation and line-breaking being the right way to code *any*
program.

> if (!this_v->c) /* vertical polyg segmt */ { if (xf == this_v->x) /*
> matching X-value */ { if (yf == this_v->y) /* matching Y-value */ { if
> (this_v->y > next_v->y) /* North end of segment */ { if (this_v->x >

<Snip! Help! My eyes can't stand it!>

(If this was a newsreader artifact, then get a better newsreader. It looks
like your article came from DejaNews; that makes this a pretty good argument
for not posting via DejaNews.)

--
Aaron Crane <aaron...@pobox.com> <URL:http://pobox.com/~aaronc/>

0 new messages