[comp.lang.c] if

denbeste@bgsuvax.UUCP (William C. DenBesten) (01/29/88)

>	if	(a);
>		stat1;

>	for (i = 1; i < 100; i++);
>		fn3 (argument, i);

> Indentation is IGNORED by Lint and the compiler, but is superficially VERY
> significant to we visually oriented beings.  Thus the occasional problem
> in spotting the above class of errors.

This statement hits a nail squarely on its head.  I used to have
terrible problems with C syntax as I was learning C.  I then
discovered c-mode in GNU emacs.  Its basic trick is that it indents
the current line properly, depending on the lines before it.  I
commonly make the above errors, forget to close a quote or
parenthesis, and a myrid of other errors.  When I hit tab and the line
isn't adjusted to where I expect it to be, I know to take a look at
the previous couple of lines, and voila a typo is uncovered.

Another way to find this sort of error is to run your code through a c
beautifier (cb) and look at the way that it indents the code.  Of
course, you have to be suspecting this sort of error to even think
about attemptin this.

---
          William C. DenBesten | CSNET denbeste@research1.bgsu.edu
      Dept of Computer Science | UUCP  ...!cbosgd!osu-cis!bgsuvax!denbeste
Bowling Green State University |
  Bowling Green, OH 43403-0214 |

hascall@cs.iastate.edu (John Hascall) (03/24/90)

    Ok, style mavens, which is "better":

    if (e1) return e2;                    if (e1) return e2;
    else s1;                              s1;

---------------------------------------------------------------
    I'm not sure which of the above is better, but I am sort of
    "stuck on" the following convention:

    if (e1) s1;        \
      --or--            \
    if (e1) {           | Does this seem reasonable?
	s1;             | (ignoring whether or not the `{'
    }                   | belongs on the next line or not)
    --but never--       |
    if (e1)             /
	s1;            /

Stylistically yours,
John Hascall
hascall@atanasoff.cs.iastate.edu

chrisl@caen.engin.umich.edu (Chris Lang) (03/24/90)

In article <887@dino.cs.iastate.edu> hascall@cs.iastate.edu (John Hascall) writes:
>    I'm not sure which of the above is better, but I am sort of
>    "stuck on" the following convention:
>
>    if (e1) s1;        \
>      --or--            \
>    if (e1) {           | Does this seem reasonable?
>	s1;             | (ignoring whether or not the `{'
>    }                   | belongs on the next line or not)
>    --but never--       |
>    if (e1)             /
>	s1;            /

I'm probably not one to be talking about style, but...  I agree.  In fact,
I go so far as to never use the first form (almost).  I also like to spread
things out a little more, so it looks more like:
    if (spam->flags | EATEN)
        {
        Barf();
        } /* if */
    else
        {
        OnlyGetQueasy();
        } /* else */

The third form I never use, since I otherwise find myself forgetting to enclose
's1' in braces if I go back and add a second statement.  (I will use it on 
rare occasions in long lists of if/elseif/else's where I am 99.9% sure I will
not be adding any other statements, since otherwise they'd take up way too much
much room, especially given my style of indentation and { placement...)

OTOH, I change my style often enough that if you asked me this question six
months from now, I'd probably vehemently criticize such a preposterous
proposition. :-)

 -Chris
--
Chris Lang, University of Michigan, College of Engineering    +1 313 763 1832
      4622 Bursley, Ann Arbor, MI, 48109          chrisl@caen.engin.umich.edu 
WORK: National Center for Manufacturing Sciences, 
      900 Victors Way, Suite 226, Ann Arbor, MI, 48108        +1 313 995 0300
"I hate quotations.  Tell me what you know."  - Ralph Waldo Emerson

ark@alice.UUCP (Andrew Koenig) (03/25/90)

Some people take the view that except at the end of a function,
`return' is just a funny way of spelling `goto.'
-- 
				--Andrew Koenig
				  ark@europa.att.com

daves@hpopd.HP.COM (Dave Straker) (03/25/90)

/ hascall@cs.iastate.edu (John Hascall) /  8:50 pm  Mar 23, 1990 /writes:
>
>    Ok, style mavens, which is "better":
>
>    if (e1) return e2;                    if (e1) return e2;
>    else s1;                              s1;

I'd vote for the second one, unless the rest of the function is contained in
s1. Thus, 

     if (e1) return e2;
     else s1;
     s2;

..would be bad style, as s1 and s2 are both going to get done, and shouldn't
be separated. Using the 'else' is giving an explicit message 'there are two
choices here'. Not using 'else' means that s1 is something new, and has little
to do with what has gone before.

>
>---------------------------------------------------------------
>    I'm not sure which of the above is better, but I am sort of
>    "stuck on" the following convention:
>
>    if (e1) s1;        \
>      --or--            \
>    if (e1) {           | Does this seem reasonable?
>	s1;             | (ignoring whether or not the `{'
>    }                   | belongs on the next line or not)
>    --but never--       |
>    if (e1)             /
>	s1;            /
>
>Stylistically yours,
>John Hascall

I would never use the first version, as I prefer to keep one item per line.
The 's1' is easily lost to those not used to this sort of stuff (style rule
no. 1: Think Of The Reader).

The second version is putting a single statement into braces. I would do this,
as it is clear that this is a consequence of the 'if'. It also makes it easier 
to insert lines later. Also, if you have a programmable editor, you can program
'if' to automatically add the braces and position the cursor.

I actually prefer one of the other bracing styles, either 'Whitesmiths':

     if (e1)
     {
	 s1;
     }

or 'Allman' (the names came from an 'emacs' manual, BTW):

     if (e1)
	 {
	 s1;
	 }

I will admit to using Whitesmiths most often, as I was (duck) brought up
on Pascal, although it has several advantages over K&R, eg.

     if ( complex expression that wraps
	  to next line )
     {
	 statement;
	 statement;
     }

..is clearer where the block is than:

     if ( complex expression that wraps
	  to next line ) {
         statement;
         statement;
     }

However, Allman does this and is more consistent with single statement (no
braces) after the 'if' line, as it has the simple rule, 'after the 'if', indent 
the following statement. It also allows the statements of a function to start
in column 1. Look what happens if you do this with K&R or Whitesmiths:

int foo()
{

if (e1)
{
    s1;
}
}

ouch! braces at the same level.

Regards,

Dave (brace yourself) Straker

hascall@cs.iastate.edu (John Hascall) (03/26/90)

In article <10624@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes:
}Some people take the view that except at the end of a function,
}`return' is just a funny way of spelling `goto.'

  There's no accounting for taste, I guess...                :-)

  Anyhow, I took a stroll through K&R1 and lo and behold (oh dear,
  say it isn't so!) I found `return's not at the end of a function:

    FUNCTION  PAGE 
    binary      54
    index       67
    push        75
    pop         75
    getop       78
    alloc       97
    strcmp     101
    strcmp     102
    readlines  107
    numcmp     117
    binary     125
    getword    127
    type       127
    binary     129
    lookup     135
    install    136
    (got tired of looking...you get the point)

-----------------------------------------------------------------------
Also, I found a couple of interesting remarks on: return ( expr )

[page 68]   ... Any expression can follow return:

                   return(expression)

[page 70]   ... The value of the expression in

		   return(expression)

	    is always converted ...
-----------------------------------------------------------------------

John Hascall
hascall@atanasoff.cs.iastate.edu

mikes@rtech.UUCP (Mike Schilling) (03/26/90)

From article <10624@alice.UUCP>, by ark@alice.UUCP (Andrew Koenig):
> Some people take the view that except at the end of a function,
> `return' is just a funny way of spelling `goto.'
A shop of horrors I once worked in used the following coding standard, thinking
it was good style:

1. Only one return statement per function.
2. No goto's, even for error handling.
3. Tabs are eight spaces wide, as ASCII intended.

The result, of course, was that any function which did input argument 
checking began its useful life indented at least 32 spaces, and ended:
				}
			}
		}
	}
	return(error_status);
}

I've always thought that leaving the main processing code once it's
clear that special error processing is needed makes code both easier to read
and more maintainable.
----------------------------------------------------------------------------
mikes@rtech.com = Mike Schilling, Ingres Corporation, Alameda, CA
Just machines that make big decisions,
Programmed by fellows with compassion and vision.	-- Donald Fagen, "IGY"

chrisl@caen.engin.umich.edu (Chris Lang) (03/26/90)

In article <7990006@hpopd.HP.COM> daves@hpopd.HP.COM (Dave Straker) writes:
>However, Allman does this and is more consistent with single statement (no
>braces) after the 'if' line, as it has the simple rule, 'after the 'if', indent 
>the following statement. It also allows the statements of a function to start
>in column 1. Look what happens if you do this with K&R or Whitesmiths:
>
>int foo()
>{
>
>if (e1)
>{
>    s1;
>}
>}
>
>ouch! braces at the same level.

That reminds me to ask, what about this, which is basically my style?

void foo(struct spam *bar)
    {
    if (bar->bletch != NULL)
        {
        printf("Ve haf a bletch!\n");
        } /* if */
    else
        {
        bar->bletch = 6;
        printf("We have one NOW!\n");
        } /* else */
    return;
    } /* foo() */

The point I am most interested in is the indentation of the entire function,
including opening and closing braces.  Does this strike people as possibly
confusing?  I find it clearer, and consistant (ie, every sub-block gets
indented, as do its opening and closing braces).  I feel the final /* foo () */
makes it obvious that we're at the end of a function, not one level in...
but what do others feel?

Thanks...

 -Chris



>
>Regards,
>
>Dave (brace yourself) Straker


--
Chris Lang, University of Michigan, College of Engineering    +1 313 763 1832
      4622 Bursley, Ann Arbor, MI, 48109          chrisl@caen.engin.umich.edu 
WORK: National Center for Manufacturing Sciences, 
      900 Victors Way, Suite 226, Ann Arbor, MI, 48108        +1 313 995 0300
"I hate quotations.  Tell me what you know."  - Ralph Waldo Emerson

jdudeck@polyslo.CalPoly.EDU (John R. Dudeck) (03/26/90)

In article <887@dino.cs.iastate.edu> hascall@cs.iastate.edu (John Hascall) writes:
>
>    Ok, style mavens, which is "better":
>
>    if (e1) return e2;                    if (e1) return e2;
>    else s1;                              s1;
I can't think of any reason why one is better than the other, but I think
that the second one indicates that you have thought through the logic of
the routine enough to realize that the 'else' is superfluous.  Whenever
I notice that I have done the first, I always change it to remove the else.
>
>---------------------------------------------------------------
>    I'm not sure which of the above is better, but I am sort of
>    "stuck on" the following convention:
>
>    if (e1) s1;        \
>      --or--            \
>    if (e1) {           | Does this seem reasonable?
>	s1;             | (ignoring whether or not the `{'
>    }                   | belongs on the next line or not)
>    --but never--       |
>    if (e1)             /
>	s1;            /
>
I discovered a good reason to use the third form.  When you are
debugging with CodeView, if the action is on a separate line from the
condition you can breakpoint on the action, and it will only break
if that branch is taken.  Similarly, you can single step and have it
stop on the action part.

Otherwise I always use the first two (including your placement of '{' ).

-- 
John Dudeck                           "You want to read the code closely..." 
jdudeck@Polyslo.CalPoly.Edu             -- C. Staley, in OS course, teaching 
ESL: 62013975 Tel: 805-545-9549          Tanenbaum's MINIX operating system.

jamiller@hpcupt1.HP.COM (Jim Miller) (03/27/90)

>>    Ok, style mavens, which is "better":
>>
>>    if (e1) return e2;                    if (e1) return e2;
>>    else s1;                              s1;

I'd vote for the second one.

>
>or 'Allman' (the names came from an 'emacs' manual, BTW):
>
>     if (e1)
>	 {
>	 s1;
>	 }

I like that one, because I prefer the following:

     if (e1) {
	 s1;
	 }

(IMHO) I don't think I "lose" anything by putting the { with the if, but I
think I do if the } is not on a separtate line.

   jim  miller

utility@quiche.cs.mcgill.ca (Ronald BODKIN) (03/27/90)

In article <10624@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes:
>Some people take the view that except at the end of a function,
>`return' is just a funny way of spelling `goto.'
Is this reallly a clearer and neater way of coding:
int foo()
{
	int ret;
	if (cond1) {
		/* do stuff */
		ret=1;
	}
	else {
		/* do other stuff */
		ret=2;
	}
	return ret;
}

This is slower and more cumbersome, IMHO.  After all, while and until
and for are also funny ways of spelling goto...
	Ron

Markku.Savela@tel.vtt.fi (Markku Savela) (03/27/90)

In article <1990Mar25.222115.7161@caen.engin.umich.edu> chrisl@caen.engin.umich.edu (Chris Lang) writes:

>That reminds me to ask, what about this, which is basically my style?

   Well, I have been using about the same style, except I indent braces
half way between code indenting points. (Chris example reformatted):

void foo(struct spam *bar)
    {
    	if (bar->bletch != NULL)
		printf("Ve haf a bletch!\n");
	else
	   {
		bar->bletch = 6;
		printf("We have one NOW!\n");
	   }
	return;
    }

    And, as I uses emacs, I don't have to ident myself, emacs C mode
does most of the work, also catches any any unbalanced braces or
parethesis very easy (when you hit <tab> and don't end up where you
expect, it's time to start looking the missing brace or parenthesis ;)

    I don't use braces unless needed, because with this style it's
very hard to make mistake (with editor C mode helping...)

--
Markku Savela                         | savela@tel.vtt.fi
Technical Research Centre of Finland  |
Telecommunications Laboratory         | Markku.Savela@vtt.fi
Otakaari 7 B, SF-02150 ESPOO, Finland | savela%vtttel@router.funet.fi 

jamiller@hpcupt1.HP.COM (Jim Miller) (03/28/90)

>void foo(struct spam *bar)
>    {
>    if (bar->bletch != NULL)
>        {
>        printf("Ve haf a bletch!\n");
>        } /* if */
>    else
>        {
>        bar->bletch = 6;
>        printf("We have one NOW!\n");
>        } /* else */
>    return;
>    } /* foo() */
>
>The point I am most interested in is the indentation of the entire function,
>including opening and closing braces.  Does this strike people as possibly
>confusing?  I find it clearer, and consistant (ie, every sub-block gets
>indented, as do its opening and closing braces).  I feel the final /* foo () */
>makes it obvious that we're at the end of a function, not one level in...
>but what do others feel?

My style is:

void foo(struct spam *bar)
{
    if (bar->bletch != NULL)
        {
	. . .
	}
     . . .
     return;
} /* foo */

which makes procedure {}  inconsistant with all my other {}'s.  However,
it's so vi's "[[" and "]]" commands can find them.  I indent the procedure
body so procedure declaration and other global declarations visually stand
out.

>
>Thanks...
>
> -Chris

You're welcome.
   jim


P.S. 

>After all, while and until
>and for are also funny ways of spelling goto...
>	Ron
 
 So is "if"  :-)
       

braun@drivax.UUCP (Kral) (03/29/90)

In article <2637@quiche.cs.mcgill.ca> utility@quiche.cs.mcgill.ca (Ronald BODKIN) writes:
>Is this reallly a clearer and neater way of coding:
>int foo()
>{
>	int ret;
>	if (cond1) {
>		/* do stuff */
>		ret=1;
>	}
>	else {
>		/* do other stuff */
>		ret=2;
>	}
>	return ret;
>}

I say yes.  In addition, it's easier to modify (say you want to do some further
processing before you return), and it's easier to debug with a debugger, as
there is only one place you have to break to stop the return.

-- 
kral 	408/647-6112			...amdahl!drivax!braun
"To surrender is to remain in the hands of barbarians for the rest of my life;
 To fight is to leave my bones exposed in the desert waste" 
		- ancient chinese poem

emuleomo@paul.rutgers.edu (Emuleomo) (03/29/90)

In article <10624@alice.UUCP>, ark@alice.UUCP (Andrew Koenig) writes:
> Some people take the view that except at the end of a function,
> `return' is just a funny way of spelling `goto.'
> -- 
> 				--Andrew Koenig
> 				  ark@europa.att.com

Yeah, but this <goto> can be really beneficial if used properly.
Consider

main()
{
	if (<condition>) return(FAILURE);

	a +=b;
	etc...
	etc...
	etc...
	return(SUCCESS);
}

AND

main()
{
	if (<condition>)
		status_code = FAILURE;
	else
	{
		a +=b;
		etc...
		etc...
		etc...
		status_code = SUCCESS;
	}
	return(status_code);
}

Somehow, I think the former is becomes easier to comprehend as the size of
the code "inside" the else clause get larger.

--Emuleomo O.O. (emuleomo@yes.rutgers.edu)
-- 
*Nothing* is hard.   If it looks hard, you are looking at it the hard way!

robert@isgtec.UUCP (Robert A. Osborne) (03/29/90)

In article <1990Mar25.222115.7161@caen.engin.umich.edu> chrisl@caen.engin.umich.edu (Chris Lang) writes:
>That reminds me to ask, what about this, which is basically my style?
>
>void foo(struct spam *bar)
>    {
>    } /* foo() */
Breaks ]] and [[ in vi. The only indenting I can support is
    func()
    {
        if() {
           /* stuff */
        }
    }
or
    func()
        if()
        {
           /* stuff */
        }
    }

If you are writing code that no one, absolutely no one, but yourself
will look at, do what ever you want.  If you are writing code for others
to read it should be K&R, a style most people are at least familiar with,
if not a style they are already using.

Rob.
-- 
Robert A. Osborne   {...uunet!mnetor,...utzoo}!lsuc!isgtec!robert 

mikem> (04/13/90)

>In article <1461@tkou02.enet.dec.com> diamond@tkou02.enet.dec.com (diamond@tkovoa) writes:
>>In article <656@hades.OZ> greyham@hades.OZ (Greyham Stoney) writes:
>>
>>      if (buffer) free(buffer)
>>
>>This is also portable, and almost readable.  Again, to be really readable,
>>you should still compare to NULL, but I grant that it would make your
>>source code longer this time.
>
>How about just a:
>        free(buffer)
>
>The manual pages I know allow a NULL pointer and doing nothing in this case.
>Is this generally true ?

Using the free function with a NULL pointer may be o.k with some 
compilers, but don't try that with other functions since you may get 
unpredictable results.  Using MSC 5.1 I had a few calls which didn't 
check to see if the pointer was NULL prior to calling fclose(fileptr), 
and fclose ended up writing garbage into the interrupt vector table.
-- 
Michael Morris, Strategic Mapping Inc.      {hpda,pyramid}!octopus!slp!mikem

andrew@csd4.csd.uwm.edu (Andy Biewer) (08/17/90)

Much of the time during programming in C I run into the same question about
conditional statements such as the subject.  I have been wondering for quite
some time now about what, if any, differences there are between the two
conditional statements:

  1)  if ( x && y )
          statement;

  2)  if ( x )
          if ( y )
               statement;

It may be a trivial question, however, is there any?  Will `y' in the first
conditional be tested if `x' fails?  I know that it won't in the second.

Because it's a conjunction, logically it is unnecessary to test `y' because
the whole evaluation is false if `x' fails.  And, of course, with a
disjunction it would be necessary to test `y'.  But, is the compiler smart
enough to take these facts into consideration (or is it even possible to)?

Andy B.

gvr@cs.brown.edu (George V. Reilly) (08/17/90)

In article <5781@uwm.edu> andrew@csd4.csd.uwm.edu (Andy Biewer) writes:
% Much of the time during programming in C I run into the same question about
% conditional statements such as the subject.  I have been wondering for quite
% some time now about what, if any, differences there are between the two
% conditional statements:
% 
%   1)  if ( x && y )
%           statement;
% 
%   2)  if ( x )
%           if ( y )
%                statement;
% 
% It may be a trivial question, however, is there any?  Will `y' in the first
% conditional be tested if `x' fails?  I know that it won't in the second.
% 
% Because it's a conjunction, logically it is unnecessary to test `y' because
% the whole evaluation is false if `x' fails.  And, of course, with a
% disjunction it would be necessary to test `y'.  But, is the compiler smart
% enough to take these facts into consideration (or is it even possible to)?

Yes, not only is it smart enough to, but it is required to.  From K&R2, p. 21,
	"Expressions connected by && and || are evaluated left to right,
	 and it is guaranteed that evaluation will stop as soon as the
	 truth or falsehood is known."

This is also known as short-circuiting Boolean expressions.

[I wonder how many people will jump in and post followups to Andy's
 question without checking to see if anybody else has done so.  Just
 hope I don't end up with egg on my face for making this remark.]
________________
George V. Reilly			gvr@cs.brown.edu
uunet!brunix!gvr   gvr@browncs.bitnet	Box 1910, Brown U, Prov, RI 02912

karl@haddock.ima.isc.com (Karl Heuer) (08/17/90)

In article <5781@uwm.edu> andrew@csd4.csd.uwm.edu (Andy Biewer) writes:
>I have been wondering for quite some time now about what, if any, differences
>there are between the two conditional statements:
>  1)  if ( x && y ) statement;
>  2)  if ( x ) if ( y ) statement;

If each represents an entire statement, then the two are semantically
identical (the language *requires* that `y' not be tested if `x' fails), and
the main advantage of (1) is conciseness.

Things change if you add an `else' clause: `if (x && y) s1; else s2;' is
equivalent to `if (x) { if (y) s1; else s2; } else s2;' and the presence of
the `&&' operator saves you from having to duplicate code%.  Similarly,
`while (x && y) s;' is much cleaner than the equivalent code written without
`&&'.  So, `&&' is more than just syntactic sugar for `if...if'.

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint
________
% Yes, one could also emulate `&&' without duplicating the code.  The point
  is, `&&' is better than `if...if' in this case.

jdarcy@encore.com (Mostly Harmless) (08/17/90)

andrew@csd4.csd.uwm.edu (Andy Biewer) writes:
>I have been wondering for quite
>some time now about what, if any, differences there are between the two
>conditional statements:
>
>  1)  if ( x && y )
>          statement;
>
>  2)  if ( x )
>          if ( y )
>               statement;

I can't say whether or not this is standard behaviour, but all of the compilers
I've worked with will use "short-circuited evaluation" for the first construct.
In other words, condition "y" will NOT be evaluated if condition "x" is false.

The major difference between the two forms is the meaning of an "else" after
each.  Don't laugh; I've seen dozens or possibly hundreds of bugs caused by
this and similar logic errors.  In the first form, an else will be executed
if (!x || !y), whereas in the second it will be executed if (x && !y).  Even
if you put braces around the second "if", an else will only be executed when
(!x).

--

Jeff d'Arcy, Generic Software Engineer - jdarcy@encore.com
      Nothing was ever achieved by accepting reality

gary@hpavla.AVO.HP.COM (Gary Jackoway) (08/17/90)

Andy asks:
> I have been wondering for quite
> some time now about what, if any, differences there are between the two
> conditional statements:
> 
>   1)  if ( x && y )
>           statement;
> 
>   2)  if ( x )
>           if ( y )
>                statement;

The language C guarantees "partial evaluation".  That is, if x yields 0,
y will not be evaluated at all.  That means that if y involves a function
call, the function will not be called.

So, for example, the following code is safe in C:

    if (pointer!=NULL && pointer->i == 3)

You cannot say this in Pascal, because if the pointer is NULL the 
derefence will still occur and that's not good.  (Most Pascals have a
PARTIAL_EVAL switch to allow for this.)

So the only real difference between 1 and 2 above is that you can write
an else clause on the intermediate cases:

if (x)
   if (y) s1;
   else s2;
else s3;

Note that partial evaluation also holds for the || operator as well: if 
the first operand yields non-zero, the second operand will not be evaluated.

Gary Jackoway

huggins@zip.eecs.umich.edu (James K. Huggins) (08/17/90)

In article <5781@uwm.edu> andrew@csd4.csd.uwm.edu (Andy Biewer) writes:
| [...] I have been wondering for quite
|some time now about what, if any, differences there are between the two
|conditional statements:
|
|  1)  if ( x && y )
|          statement;
|
|  2)  if ( x )
|          if ( y )
|               statement;
|
|It may be a trivial question, however, is there any?  Will `y' in the first
|conditional be tested if `x' fails?  I know that it won't in the second.
K&R 2 specify that if 'x' fails (i.e. has value 0), 'y' will not be
tested.
 
Jim Huggins, Univ. of Michigan

gary@hpavla.AVO.HP.COM (Gary Jackoway) (08/18/90)

George Reilly writes:

> [I wonder how many people will jump in and post followups to Andy's
>  question without checking to see if anybody else has done so.  Just
>  hope I don't end up with egg on my face for making this remark.]


Well, maybe you're missing the inherent relativity of the net.

I posted MY response before MY node had YOUR response.
	AND
YOU posted YOUR response before YOUR node had MY response.

So, of course duplicate responses are going to happen frequently.
From the perspective of all notes readers on my node, you have egg on your face.

Gary Jackoway

mat@mole-end.UUCP (Mark A Terribile) (08/18/90)

> ... I run into the same question about conditional statements such as
> the subject.  ... what, if any, differences there are between the two
> conditional statements:
 
>   1)  if ( x && y )
>           statement;
 
>   2)  if ( x )
>           if ( y )
>                statement;
 

The real differences become apparent if you try to hang else's on them.
For the first one, you can write

	if( x && y )
		then_part;
	else
		else_part;

For the second, you must write

	if( x )
	{
		if( y )
			then_part;
		else
			else_part;
	}
	else
		else_part;

This might seem elementary and trite, but I have seen people lose track
of the structure of code that exceeds about twelve lines and fail to turn
code that looks like the second example into the first example.  And yes,
you should.  How can code that is twice as large as it should be be
anything but a hindrance to reliability, maintainability, readability,
etc.?  The duplication of a case is (perhaps) the worst part of all.

> It may be a trivial question, however, is there any?  Will `y' in the first
> conditional be tested if `x' fails?  I know that it won't in the second.

> Because it's a conjunction, logically it is unnecessary to test `y' because
> the whole evaluation is false if `x' fails.  And, of course, with a
> disjunction it would be necessary to test `y'.  ...

Ah, now the truth comes out!

One of the great things about C (as opposed to FORTRAN or PASCAL or PL/I)
is that the logical operators `short-circuit'.  &&  and  ||  evaluate left-to-
right AND ONLY AS FAR AS NECESSARY.  In K&R-I, this is explained on page 19
and again on page 38.  In K&R-II, in just about the same words, it is
explained on pages 21 and 41.  What, you used some other textbook?  No, don't
tell us about it, please.

> 					     ...  But, is the compiler smart
> enough to take these facts into consideration (or is it even possible to)?

Yes, the compiler is smart enough; it is required to by the language, and
it really isn't so difficult to program.  Once you've got the expression
tree, it's fairly simple and pretty much machine independent (RISC
optimizations being handled later).

Incidentally, the Bourne and Korn shell && and || have the same property.

For those who have been bored this far and who don't know it, the designers
of Ada couldn't decide whether to have the logical AND and OR short-circuit
(allowing shorter code in programs that can use the feature) or not (allowing
the compiler to decide which operand is cheaper to compute and computing that
operand first).  They ended up with both kinds,  AND and AND THEN, OR and
OR ELSE.  Just like a spoiled rich kid who can't decide which to buy, DOD
bought both.  I read some where that short-circuits were outnumbering
reorderables by three to one in actual code, but that was a while ago.  It
may have changed.
-- 

 (This man's opinions are his own.)
 From mole-end				Mark Terribile

andrew@csd4.csd.uwm.edu (Andrew David Biewer) (08/21/90)

From article <426@mole-end.UUCP>, by mat@mole-end.UUCP (Mark A Terribile):
[ ... if ... then ... else ... STUFF ... ]

> explained on pages 21 and 41.  What, you used some other textbook?  No, don't
> tell us about it, please.

But I must.  So many people have referred to K&R's I && II and I guess my
first mistake was not telling everyone that I don't have a single copy of a
C book.  *SIGH*  Oh well, the place of my new employment has a C++ book, I
guess I'll start moving in that direction now.

Thanks,
Andy B.

dwg@bpdsun1.uucp (David W. Glessner) (08/22/90)

In article <5824@uwm.edu> andrew@csd4.csd.uwm.edu writes:
>From article <426@mole-end.UUCP>, by mat@mole-end.UUCP (Mark A Terribile):
>[ ... if ... then ... else ... STUFF ... ]
>
>> explained on pages 21 and 41.  What, you used some other textbook?  No, don't
>> tell us about it, please.
>
>But I must.  So many people have referred to K&R's I && II and I guess my
>first mistake was not telling everyone that I don't have a single copy of a
>C book.

No, the first mistake was not having a single copy of a C book ;-).
--
David	WU9A	quintro!bpdsun1!dwg@lll-winken.llnl.gov
		uunet!tiamat!quintro!bpdsun1!dwg

siva@bally.Bally.COM (Siva Chelliah) (09/12/90)

In article <1990Aug17.164730.25750@zip.eecs.umich.edu> huggins@zip.eecs.umich.edu (James K. Huggins) writes:
>In article <5781@uwm.edu> andrew@csd4.csd.uwm.edu (Andy Biewer) writes:
>| [...] I have been wondering for quite
>|some time now about what, if any, differences there are between the two
>|conditional statements:
>|
>|  1)  if ( x && y )
>|          statement;
>|
>|  2)  if ( x )
>|          if ( y )
>|               statement;
>|
>|It may be a trivial question, however, is there any?  Will `y' in the first
>|conditional be tested if `x' fails?  I know that it won't in the second.
>K&R 2 specify that if 'x' fails (i.e. has value 0), 'y' will not be
>tested.
> 
>Jim Huggins, Univ. of Michigan

I was told by my teachers that this is compiler dependent.  Some compilers will
evaluate both x and y first before evaluating ( x && y).  If so, you will get
into trouble when you try to execute the following statement ( in fact this
is a neat way (?) to test how your compiler works!)
      if (x >0 && 5/x)
         statement
if x=0 , your program will crash!
I am glad that new ANSI C uses short circuiting.  
    Furthermore, I read somewhere that you should not use if ... then if 
(under structured programming principles I guess), so the following stmt : 
        if (x)
           if (y)
              statement1
           else
              statement2
        else
           statement3

should  be re-written as
          if (!x)
             statement3
          else if (y)
                  statement1
               else
                  statement2
I want some feed back on this if ... else stuff.  Thanks.

dbrooks@osf.org (David Brooks) (09/12/90)

In article <367@bally.Bally.COM>, siva@bally.Bally.COM (Siva Chelliah) writes:
|> I was told by my teachers that this is compiler dependent.  Some
compilers will
|> evaluate both x and y first before evaluating ( x && y).

Your next step is to go to this teacher and demand your tuition fees
back.  One of three possible explanations:

- The teacher doesn't know what s/he is talking about.

- The teacher has seen a compiler with this behavior and didn't
  properly explain that it is broken and should be avoided at all
  costs.  It will fail to compile thousands of correct programs.

- The teacher was talking about some other language, not C, and didn't
  detect you in the wrong class.

Strictly, your second sentence should say "Some compilers will
produce code that will evaluate..."

|>     Furthermore, I read somewhere that you should not use if ... then
if 
|> (under structured programming principles I guess), so the following
stmt : 
|>         if (x)
|>            if (y)
|>               statement1
|>            else
|>               statement2
|>         else
|>            statement3
|> 
|> should  be re-written as
|>           if (!x)
|>              statement3
|>           else if (y)
|>                   statement1
|>                else
|>                   statement2

You are probably thinking of the "dangling else", which some of us
first met in Algol 60.  The ambiguity lies in this:

        if (x)
           if (y)
              statement1
           else
              statement2

Since compilers don't read formatting, which "if" owns the "else"?
The C answer is "by associating the "else" with the closest previous
"else"-less "if". (K&R2, p56), which is the decision implied by the
formatting above.  Your example is not ambiguous, but I would put some
redundant braces in it (no flames about that, please).

Do I detect the resumption of classes?
-- 
David Brooks				dbrooks@osf.org
Systems Engineering, OSF		uunet!osf.org!dbrooks
Experience Hackvergnuegen!

shirono@ssd.csd.harris.com (Roberto Shironoshita) (09/12/90)

In article <367@bally.Bally.COM> siva@bally.Bally.COM (Siva Chelliah) writes:

> In article <1990Aug17.164730.25750@zip.eecs.umich.edu> huggins@zip.eecs.umich.edu (James K. Huggins) writes:
> >In article <5781@uwm.edu> andrew@csd4.csd.uwm.edu (Andy Biewer) writes:
> >| [ wonders about "if (x && y) stmt;" and "if (x) if (y) stmt;" ]
> >K&R 2 specify that if 'x' fails (i.e. has value 0), 'y' will not be
> >tested.
> I was told by my teachers that this is compiler dependent.  Some
> compilers will 
> evaluate both x and y first before evaluating ( x && y).

Let's get things straight.

The LANGUAGE specifies lazy evaluation:

K&R (1ed) p. 38  [emphasis mine]:
	More interesting are the logical connectives && and ||.
	Expressions connected by && or || are evaluated left to
	right, **>and evaluation stops as soon as the truth or
	falsehood of the result is known<***

If some compiler doesn't do this, then it doesn't compile C, and never did.

SIDE NOTE: Pascal either allows or requires full evaluation of every
	expression.
--

     Roberto Shironoshita      ||   Internet: shirono@ssd.csd.harris.com
      Harris Corporation       ||
   Computer Systems Division   ||   UUCP:     ...!uunet!hcx1!shirono
                               ||
DISCLAIMER: The opinions expressed here are my own; they in no way reflect the
            opinion or policies of Harris Corporation.

news@ism780c.isc.com (News system) (09/19/90)

In article <1990Sep15.195547.2861@sea.com> keck@sea.com (John Keck) writes:
>
>K&R, original edition, p. 19: "Expressions connected by && or || are
>evaluated left to right, and it is guaranteed that evaluation will stop
>as soon as the truth or falsehood is known."
>
>Does any one know of a C compiler which does *not* short ciruit these operators?
>

I know of one that did not do short circuit (it does now :-) in the following
case:

   a = -1;  b = 1;
   ++a && ++b;

In this example b had the value 2 after execution of the second line.  The
reason I am aware of the problem is that I had to fix the bug (I did not
write the compiler).  The compiler worked properly when the && appeared
inside an 'if', 'while' or as the second expression in a 'for'.

BTW: the bug was not found by the compiler validation suite.  The compiler
was also used to compile all of the Unix sources without the bug showing
up.  So there might be other compilers with a similar unknown bug.

   Marv Rubinstein