Goto still considered helpful - C
This is a discussion on Goto still considered helpful - C ; Keith Thompson wrote, On 19/10/07 07:29:
> Ben Pfaff <blp@cs.stanford.edu> writes:
>> CBFalconer <cbfalconer@yahoo.com> writes:
>>> int fcopy(char const *dst, char const *src) {
>>> FILE *sf, *df;
>>> int ch
>>>
>>> if (sf = fopen(src, "r") { /* ...
-
Re: Goto still considered helpful
Keith Thompson wrote, On 19/10/07 07:29:
> Ben Pfaff <blp@cs.stanford.edu> writes:
>> CBFalconer <cbfalconer@yahoo.com> writes:
>>> int fcopy(char const *dst, char const *src) {
>>> FILE *sf, *df;
>>> int ch
>>>
>>> if (sf = fopen(src, "r") { /* text files */
>>> if (df = fopen(dst, "w") {
>>> while (EOF != (ch = getc(sf))) putc(ch, df);
>>> fclose(df);
>>> }
>>> fclose(sf);
>>> }
>>> return sf && df; /* non-zero for success */
>> I think that this is a bad idea: it is a lot like checking the
>> value of a pointer after it has been freed (often fclose will
>> actually call free on the stream, in fact). I'm sure it works in
>> practice on almost every implementation though.
>>
>>> }
>
> If the first fopen() fails, no value is assigned to df, and accessing
> it invokes undefined behavior.
If the first fopen fails sf will be a null pointer and short circuit
evaluation ensures that df is not accessed, so it is OK.
> In addition, I think you're write; though fclose() cannot change the
> value of of its argument, it can cause it to become indeterminate.
> (In practice, it will probably appear to be be null or non-null after
> fclose() if it was, respectively, null or non-null before fclose().)
Agreed.
--
Flash Gordon
-
Re: Goto still considered helpful
On Oct 5, 5:48 am, Army1987 <army1...@NOSPAM.it> wrote:
> On Fri, 05 Oct 2007 02:18:31 -0700, James Dow Allen wrote:
> > http://james.fabpedigree.com/gotoalt.htm
> > I do hope readers will indicate which version
> > is "more readable."
>
> Most often there is a better alternative. I fail to see a good
> alternative in the code on that page, but maybe that's just
> because I'm not in good shape today.
This thread has generated several posts on a
simple goto which can be replaced simply,
but only one comment about the more interesting
goto. Come on, don't be shy!
Counting previous posts, I've received about 12 responses
on this code. Perhaps Army1987's unusually tepid
response counts as favorable. I'm grateful to Tim,
the *only* one who's ever taken the trouble to produce
a goto-free version. The other responses I've
received divide equally into two categories.
Half the responses, paraphrased, were:
> replace the common code with a function call [or
> some other response proving that respondent was
> too lazy or incompetent to grok the program at all]
The other half had the form:
> fixing your ugly code would be a minute's child
> play but I'm too busy now [presumably busy
> constructing a 99th diatribe about ignoramuses
> who write "void main()" ?]
Of course what I'd like to see :-) :-) is:
> A special convocation of C experts declared today
> that Jamie's GOTO is the most readable way to express
> a bridge solving program. Cornelia Dijkstra made
> a special appearance; she regretted that her grandfather
> couldn't come to apologize to Mr. Allen in person.
> Ms. Dijkstra has submitted a retraction to the ACM
> Bulletin on her grandfather's behalf.
But I'd be willing to live with (and indeed could then
promise to never mention GOTO in this newsgroup again)
a response like:
> After careful objective scrutiny, 4 out of 5 c.l.c
> experts agreed that Mr. Rentsch's submission was
> more readable than Mr. Allen's. In the words of
> long-time c.l.c guru Eric B. Keithfield:
> > We tried to give the jerk the benefit of the doubt,
> > but Geez Louise! A goto from one inner loop to
> > another didn't even pass the laugh test. We advised
> > Mr. Allen to rework his code and submit it to the
> > Obfuscated C Contest.
What I frankly find irritating are responses like
> fixing your ugly code would be a minute's child
> play but I'm too busy now....
> ...
> ... [wait a few months, then post in another thread]
> I've never come across
> a good reason to use goto in "real" code).
Keith Thompson wrote:
> In addition, I think you're write; ...
> Did I really write "write" instead of "right"? Sigh.
Lately I write "their" for "there", "are" for "or"
and even "haven't" for "having". Is there a name for
this condition? I'm also losing my sense of smell.
How old are you, Keith?
James Dow Allen
-
Re: Goto still considered helpful
CBFalconer <cbfalconer@yahoo.com> writes:
> So look at the following, with a single return, and no complexity:
>
> int fcopy(const char *dst, const char *src) {
> FILE *sf, *df;
> int err, ch;
>
> if (!(sf = fopen(src, "r"))) err = 1;
> else if (!(df = fopen(dst, "w"))) err = 2;
> else {
> while (EOF != (ch = getc(sf))) putc(ch, df);
> err = 0;
> fclose(df);
> }
> if (sf) fclose(sf);
> return err;
> }
To any nOOB out there, please never, ever follow the style above. It is
tantamount to blasphemy to put more than one statement on a line in C
with a condition.
e.g
> if (sf) fclose(sf);
SHOULD be in any decent code base
if (sf)
fclose(sf);
Why? So that in the case of stepping through in a debugger you can see
if the fclose was executed or not. There is a group in c.l.c that think
using a debugger is "twice as hard as writing the code in the first
place" and apparently they never, ever use debuggers. I think they are
dreaming. While there may be an element of truth in doing it right the
first time, it bears no scrutiny in the real world where other people
have to debug other peoples code all the time a long time after it was
written. Be structuring your code to be debugger friendly, you will earn
the thanks of many, many people in the years to come.
-
Re: Goto still considered helpful
James Dow Allen <jdallen2000@yahoo.com> writes:
[...]
> Keith Thompson wrote:
>> In addition, I think you're write; ...
>> Did I really write "write" instead of "right"? Sigh.
>
> Lately I write "their" for "there", "are" for "or"
> and even "haven't" for "having". Is there a name for
> this condition? I'm also losing my sense of smell.
>
> How old are you, Keith?
Older than I've ever been.
--
Keith Thompson (The_Other_Keith) kst-u@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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
-
Re: Goto still considered helpful
Flash Gordon <spam@flash-gordon.me.uk> writes:
> Keith Thompson wrote, On 19/10/07 07:29:
>> Ben Pfaff <blp@cs.stanford.edu> writes:
>>> CBFalconer <cbfalconer@yahoo.com> writes:
>>>> int fcopy(char const *dst, char const *src) {
>>>> FILE *sf, *df;
>>>> int ch
>>>>
>>>> if (sf = fopen(src, "r") { /* text files */
>>>> if (df = fopen(dst, "w") {
>>>> while (EOF != (ch = getc(sf))) putc(ch, df);
>>>> fclose(df);
>>>> }
>>>> fclose(sf);
>>>> }
>>>> return sf && df; /* non-zero for success */
>>> I think that this is a bad idea: it is a lot like checking the
>>> value of a pointer after it has been freed (often fclose will
>>> actually call free on the stream, in fact). I'm sure it works in
>>> practice on almost every implementation though.
>>>
>>>> }
>> If the first fopen() fails, no value is assigned to df, and accessing
>> it invokes undefined behavior.
>
> If the first fopen fails sf will be a null pointer and short circuit
> evaluation ensures that df is not accessed, so it is OK.
[...]
You're right.
--
Keith Thompson (The_Other_Keith) kst-u@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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
-
Re: Goto still considered helpful
Richard <rgrdev@gmail.com> wrote:
> CBFalconer <cbfalconer@yahoo.com> writes:
>
> > So look at the following, with a single return, and no complexity:
> >
> > int fcopy(const char *dst, const char *src) {
> > FILE *sf, *df;
> > int err, ch;
> >
> > if (!(sf = fopen(src, "r"))) err = 1;
> > else if (!(df = fopen(dst, "w"))) err = 2;
> > else {
> > while (EOF != (ch = getc(sf))) putc(ch, df);
> > err = 0;
> > fclose(df);
> > }
> > if (sf) fclose(sf);
> > return err;
> > }
>
> To any nOOB out there, please never, ever follow the style above. It is
> tantamount to blasphemy to put more than one statement on a line in C
> with a condition.
Erm... that may be _your_ opinion, but it's hardly law.
> > if (sf) fclose(sf);
>
> SHOULD be in any decent code base
>
> if (sf)
> fclose(sf);
Depends entirely on the circumstances. If you have six of them in a row,
all similar, the first one is much neater than the second.
> Why? So that in the case of stepping through in a debugger you can see
> if the fclose was executed or not.
Get a real debugger, then. Programming tools are there to make writing
code easier, not to put demands on my style.
Richard
-
Re: Goto still considered helpful
Peter Pichler <usenet@pichler.co.uk> wrote:
> Ed Jensen wrote:
>
> > done:
> > if (sf)
> > fclose(sf);
> > if (df)
> > fclose(df);
>
> As you wish. I do not like this approach because it requires all
> declarations at the top of the function, which IMO is almost as bad
> as making them global.
Beg to differ. Beg to differ very greatly, in fact. Declarations
scattered through the code hailshot-wise are a great way of ensuring
that you'll have to hunt for one sooner or later.
> In addition, it requires them initialised to "harmless" values
> which can hide bugs later on.
No, it doesn't. For example, in the code from which the above is quoted,
the initialisations of sf and df are unnecessary: fopen() will always
return either a valid FILE *, or a null pointer, never garbage.
Richard
-
Re: Goto still considered helpful
rlb@hoekstra-uitgeverij.nl (Richard Bos) writes:
> Richard <rgrdev@gmail.com> wrote:
>
>> CBFalconer <cbfalconer@yahoo.com> writes:
>>
>> > So look at the following, with a single return, and no complexity:
>> >
>> > int fcopy(const char *dst, const char *src) {
>> > FILE *sf, *df;
>> > int err, ch;
>> >
>> > if (!(sf = fopen(src, "r"))) err = 1;
>> > else if (!(df = fopen(dst, "w"))) err = 2;
>> > else {
>> > while (EOF != (ch = getc(sf))) putc(ch, df);
>> > err = 0;
>> > fclose(df);
>> > }
>> > if (sf) fclose(sf);
>> > return err;
>> > }
>>
>> To any nOOB out there, please never, ever follow the style above. It is
>> tantamount to blasphemy to put more than one statement on a line in C
>> with a condition.
>
> Erm... that may be _your_ opinion, but it's hardly law.
No, like any style its not law. But after years of programming in
various sectors and languages it is, IMO, better to make the code
debugger friendly for those that follow.
>
>> > if (sf) fclose(sf);
>>
>> SHOULD be in any decent code base
>>
>> if (sf)
>> fclose(sf);
>
> Depends entirely on the circumstances. If you have six of them in a row,
> all similar, the first one is much neater than the second.
Neatness is nothing to do with it. Although neatness can also play a
part in readability and maintainability. This is not one of those
moments though. Its about being debugger friendly. Nothing more. (I also
find it MUCH easier to read the code too, but thats another issue).
>
>> Why? So that in the case of stepping through in a debugger you can see
>> if the fclose was executed or not.
>
> Get a real debugger, then. Programming tools are there to make writing
> code easier, not to put demands on my style.
What is a "real debugger" and which "real debugger" do you recommend?
All debuggers I have used will step by line as the default and its far
easier when the outcome of the conditional is on another line - you don't
have to *think* about "stepping in" or any some such.
I would question the merits of any programmer who thinks
if(f)func();
on one line is better for code maintenance than
if(f)
func();
>
> Richard
richard.
-
Re: Goto still considered helpful
rlb@hoekstra-uitgeverij.nl (Richard Bos) writes:
> Peter Pichler <usenet@pichler.co.uk> wrote:
>
>> Ed Jensen wrote:
>>
>> > done:
>> > if (sf)
>> > fclose(sf);
>> > if (df)
>> > fclose(df);
>>
>> As you wish. I do not like this approach because it requires all
>> declarations at the top of the function, which IMO is almost as bad
>> as making them global.
>
> Beg to differ. Beg to differ very greatly, in fact. Declarations
> scattered through the code hailshot-wise are a great way of ensuring
> that you'll have to hunt for one sooner or later.
Not with any half decent editor. Besides, locally declared variables
don't need to be hunted for. They are there where you need
them. Declaring all variables in one go at the top is bad for
maintenance and leads to confusion IMO. Declare the variable at the last
possible moment. It also keeps the locals display in your debugger
cleaner and only showing what is pertinent to the current context.
>
>> In addition, it requires them initialised to "harmless" values
>> which can hide bugs later on.
>
> No, it doesn't. For example, in the code from which the above is quoted,
> the initialisations of sf and df are unnecessary: fopen() will always
> return either a valid FILE *, or a null pointer, never garbage.
>
> Richard
-
Re: Goto still considered helpful
Richard <rgrdev@gmail.com> wrote:
> I would question the merits of any programmer who thinks
>
> if(f)func();
>
> on one line is better for code maintenance than
>
> if(f)
> func();
Of course you would. They're both evil. It should be either
if (f) func();
or
if (f)
func();
depending on context.
Any style that does not allow for "depending on context" is for the
robots, not for humans like me.
Richard
Similar Threads
-
By Application Development in forum TCL
Replies: 4
Last Post: 10-18-2007, 01:11 PM
-
By Application Development in forum RUBY
Replies: 2
Last Post: 08-16-2007, 12:54 PM
-
By Application Development in forum DOTNET
Replies: 6
Last Post: 05-15-2007, 07:10 AM
-
By Application Development in forum Java
Replies: 3
Last Post: 07-18-2006, 12:35 AM
-
By Application Development in forum basic.visual
Replies: 0
Last Post: 08-09-2004, 04:30 AM