[comp.lang.c] Unnecessary Parenthesis

daveh@marob.MASA.COM (Dave Hammond) (07/02/88)

Is different code produce by the compiler for "return n" and "return(n)" ?

How about "if (x>1 && y<2)" and "if ((x>1) && (y<2))" ? Do unnecessary
parenthesis generate more code ?

Dave Hammond
UUCP:   ...!marob!daveh
--------------------------------

chris@mimsy.UUCP (Chris Torek) (07/02/88)

In article <326@marob.MASA.COM> daveh@marob.MASA.COM (Dave Hammond) writes:
>Is different code produce by the compiler for "return n" and "return(n)" ?
>How about "if (x>1 && y<2)" and "if ((x>1) && (y<2))" ? Do unnecessary
>parenthesis generate more code ?

For these expressions, one would hope not.

On some machines, in certain expressions (including but not limited
to floating point arithmetic), `unnecessary' parentheses may cause
more code generation under dpANS rules:

	#define TWICE(x) ((x) + (x))
		...
		float p, q, r;
		...
		r = TWICE(p + q);

expands to

		r = ((p + q) + (p + q));

which might or might not be equivalent to

		r = p + p; r += q + q;

and if this cannot be determined, must be compiled as

		r = p + q; r += p + q;	/* more or less */

The important problem that is being solved is that

		a = (b + c) * d;

might give 0.0 where

		a = (b * d) + (c * d);

gives `floating point overflow'.  Whether this is an ideal solution
(or even a not-too-awful one) is another argument entirely....
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

gwyn@brl-smoke.ARPA (Doug Gwyn ) (07/03/88)

In article <326@marob.MASA.COM> daveh@marob.UUCP (Dave Hammond) writes:
>Do unnecessary parenthesis generate more code ?

The answer used to be, "not using any reasonable compiler".
Under the new ANSI C honoring-parentheses rule, excessive
parentheses CAN interfere with code optimization, when they
occur in a context that might have been rearranged if the
parentheses had not been present.

My main objection to excessive parentheses is that they
make the code less readable, not more.  There are a few
cases where the C precedence rules run counter to intuition,
and in such cases sparing use of technically redundant
parentheses can help the code reader.  However, they should
not be used just because the code WRITER is unsure.  (Most C
programmers I know have a copy of the chart from K&R 1st Ed.
p. 49 taped up near their terminal.)

	if ( a < b && b < c )	/* intuitive */
	if ( (a < b) && (b < c) )	/* no better */

	if ( a << b ^ c | d )	/* have to look this up */
	if ( ((a << b) ^ c) | d )	/* no question here */

	return 0;		/* intuitive */

	return(0);	/* one wonders why the () are there */

friedl@vsi.UUCP (Stephen J. Friedl) (07/03/88)

In article <8209@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
> (Most C programmers I know have a copy of the chart from
> K&R 1st Ed. p. 49 taped up near their terminal.)

We've found it most helpful to have a little command "opchart"
that does this (and it fits on one screen quite nicely):

#------------------------ cut here ---------------------------
cat << 'EOF'

          C operator precedence/associativity chart

Arity       Operator                                    Assoc
--------------------------------------------------------------
binary    ()  []  ->  .                                 l -> r
unary     !   ~   ++  --  -  (type)  *  &  sizeof       r -> l
binary    *   /   %                                     l -> r
binary    +   -                                         l -> r
binary    <<  >>                                        l -> r
binary    <   <=  >   >=                                l -> r
binary    ==  !=                                        l -> r
binary    &                                             l -> r
binary    ^                                             l -> r
binary    |                                             l -> r
binary    &&                                            l -> r
binary    ||                                            l -> r
ternary   ?:                                            r -> l
binary    = += -= *= /= %= >>= <<= &= ^= |=             r -> l
binary    ,                                             l -> r
--------------------------------------------------------------
                                                From K&R, p 49
EOF

#------------------------ cut here ---------------------------

    Steve
-- 
Steve Friedl     V-Systems, Inc. (714) 545-6442     3B2-kind-of-guy
friedl@vsi.com     {backbones}!vsi.com!friedl    attmail!vsi!friedl
-----------Nancy Reagan on John DeLorean: "Just say snow"----------

jeff@unh.UUCP (Jeffrey E. F. Friedl) (07/04/88)

In article <8209@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
> []
> 	return 0;		/* intuitive */
> 
> 	return(0);	/* one wonders why the () are there */

Most likely because _every_ 'return' in K&R-I has those superfluous parens.
K&R-II has been "fixed" (I like 'return(e)' beter), but 10 years too late.

	*jeff*
-------------------------------------------------------------------------------
Jeffrey Eric Francis Friedl, Box 2146 Babcock House, Durham New Hampshire 03824
..!{uunet,decvax}!unh!jeff   BITNET%"j_friedl@unhh"  ..!ucbvax!kentvax!jfriedl

kenny@m.cs.uiuc.edu (07/06/88)

/* Written  1:29 pm  Jul  2, 1988 by gwyn@brl-smoke.ARPA in m.cs.uiuc.edu:comp.lang.c */
>	return(0);	/* one wonders why the () are there */

If I were asked to guess, I'd guess it's for the same reason that
things like

	return (0);

crop up in my code as well.  I learned B before I learned C, and B
required that the expression on a return statement be parenthesized,
for no particularly good reason (Although at least one version of B
had return() implemented as a FUNCTION, and not a statement!).

I suspect that Messieurs Kernighan and Ritchie got into the same
habit, for much the same reason, as they were both B programmers
before they did C.  Perhaps dmr can enlighten us?

Kevin

" Maynard) (07/06/88)

In article <8209@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>	return 0;		/* intuitive */

To a FORTRAN programmer.

>	return(0);	/* one wonders why the () are there */

1) Because it looks consistent.
2) It's intuitive to a converted Pascal or PL/I programmer.
3) The programmer has gotten used to putting parentheses around just about
   everything.

-- 
Jay Maynard, EMT-P, K5ZC...>splut!< | Never ascribe to malice that which can
uucp:       uunet!nuchat!           | adequately be explained by stupidity.
   hoptoad!academ!uhnix1!splut!jay  +----------------------------------------
{killer,bellcore}!tness1!           | Birthright Party '88: let's get spaced!

decot@hpisod2.HP.COM (Dave Decot) (07/07/88)

> >	return 0;		/* intuitive */
> 
> To a FORTRAN programmer.

And to a C programmer.  Return is a statement that modifies the default
flow of control, such as:

     goto label;		/* NOT goto(label); */
     break;			/* NOT break();     */
     continue;			/* NOT continue();  */

Return is not a function call, and it shouldn't look like one.

> >	return(0);	/* one wonders why the () are there */
> 
> 1) Because it looks consistent.

With what?  Why do you want to make it easier to confuse function calls
with statements that don't come back?

> 2) It's intuitive to a converted Pascal or PL/I programmer.

Why?  Ordinary Pascal has no return statement.

> 3) The programmer has gotten used to putting parentheses around just about
>    everything.

That may be true in your case, but it's a bug in the language design.
Parentheses are overloaded for all of the following distinct purposes:

    function calls
    if, while, and do-while statements
    casts
    type construction (used both to indicate functions and for grouping)
    function declarations
    evaluation order grouping

I see no reason to add further confusion by making flow control look like
a function call.  I use "return e;" because it's less cluttered and more
distinct.

Dave Decot
hpda!decot

mesard@bbn.com (Wayne Mesard) (07/08/88)

From article <2550075@hpisod2.HP.COM>, by decot@hpisod2.HP.COM (Dave Decot):
>> >	return 0;		/* intuitive */
>> 
>> To a FORTRAN programmer.
> 
> And to a C programmer.  Return is a statement that modifies the default
> flow of control, such as:
> 
>      goto label;		/* NOT goto(label); */
>      break;			/* NOT break();     */
>      continue;			/* NOT continue();  */
> 

Great.  I thought the idea of HLL's was to spare the programmer the
burden of thinking like s/he was inside the machine.  
return takes an *expression*.  Are there any other statements in the
language which have unparenthesized *expressions* in their form?  That
lil old zero hanging out there by itself LOOKS INCONSISTENT.  From the
compiler's point of view return is in the set of {goto, break, continue}
but this seems an unnatural and confusing view for a programmer to hold
in his head.

>> 1) Because it looks consistent.
> 
> With what?

With the rest of the language (see above).

> Why do you want to make it easier to confuse function calls
> with statements that don't come back?
> 

Glad you asked.  Because it's consistent with the two other statements
commonly used to change the flow of control in the middle of a function:
exit() and execl().


-- 
unsigned *Wayne_Mesard();        MESARD@BBN.COM        BBN Labs, Cambridge, MA

"I am catatonic.  And the drinks are on the house."
                                                     -DB

henry@utzoo.uucp (Henry Spencer) (07/08/88)

>	return(0);	/* one wonders why the () are there */

Because back in the dawn of time, they were required, and a lot of us
old fogies have never quite gotten out of the habit.  Moreover, a lot
of the early C books were written by old fogies, so the habit has been
passed down to later generations by default.

jagardner@watmath.waterloo.edu (Jim Gardner) (07/08/88)

In article <2550075@hpisod2.HP.COM> decot@hpisod2.HP.COM (Dave Decot) writes:
>> >	return(0);	/* one wonders why the () are there */
>> 
>> 1) Because it looks consistent.
>
>With what?  Why do you want to make it easier to confuse function calls
>with statements that don't come back?

consider exit() and abort()

>I use "return e;" because it's less cluttered and more
>distinct.

I use return( e ) because the parens highlight the return value.
I have no problem reading either, and I suspect most people have no
problem with either.

rwl@uvacs.CS.VIRGINIA.EDU (Ray Lubinsky) (07/08/88)

In article <8209@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
> My main objection to excessive parentheses is that they
> make the code less readable, not more.  There are a few
> cases where the C precedence rules run counter to intuition,
> and in such cases sparing use of technically redundant
> parentheses can help the code reader.  However, they should
> not be used just because the code WRITER is unsure.  (Most C
> programmers I know have a copy of the chart from K&R 1st Ed.
> p. 49 taped up near their terminal.)

When I read code I tend to browse, slowing down for the parts the require more
thought.  Something like

	if (a < b && b < c && c < d && d < e)

is going to stop my scanning a lot more often than

	if ((a < b) && (b < c) && (c < d) && (d < e))

NOT because I am unaware of C precedence rules but because the first example is
devoid of visual structure.  Maybe your eye can parse the first as easily as
the second, but I have to drop into look-at-it-more-closely mode.  If this
happens to often it reduces my overall comprehension of the code.  I'm sure
we'd both agree that the FULL parenthesization of the expression:

	if ((((a < b) && (b < c)) && (c < d)) && (d < e))

would be abominable -- in my case because it makes the expression hard to
scan without thinking about it.

As for the "return" business I think it's more clear that

	return a + b * c;

is returning a value when it's written as

	return(a + b * c);  OR EVEN  return(a+(b*c));

because in scanning mode I expect a non-void function to return an expression
and I catch the concept of here-is-an-expression a lot more quickly when I see
those entirely unnecessary parentheses.  I also think that entirely
unnecessary white space helps readability, but a little execess
parenthesization can be an acceptable substitute.

-- 
| Ray Lubinsky,                    UUCP:      ...!uunet!virginia!uvacs!rwl    |
| Department of                    BITNET:    rwl8y@virginia                  |
| Computer Science,                CSNET:     rwl@cs.virginia.edu  -OR-       |
| University of Virginia                      rwl%uvacs@uvaarpa.virginia.edu  |

walter@hpcllz2.HP.COM (Walter Murray) (07/09/88)

Dave Decot writes:

>Return is not a function call, and it shouldn't look like one.

I agree, and I don't use parentheses there.  But how do people feel
about sizeof, which is also not an operator and does not require
parentheses when its operand is an expression?  I hate to use
them, but it seems they always improve readability in that case.
Am I just braindamaged from too much Pascal?

Walter Murray

dg@lakart.UUCP (David Goodenough) (07/09/88)

From article <326@marob.MASA.COM>, by daveh@marob.MASA.COM (Dave Hammond):
> Is different code produce by the compiler for "return n" and "return(n)" ?
> 
> How about "if (x>1 && y<2)" and "if ((x>1) && (y<2))" ? Do unnecessary
> parenthesis generate more code ?

These two expressions *_SHOULD_* generate the same code on any decent
self respecting compiler (They do even on BDS C 1.43 under CP/M :-). It
is worth noting that this is a weakness of RD parsers: the amount of
work incurred by unnecessary parentheses is quite considerable, especially
in a language such as C, with 15 levels of operator precedence. As for
LR parsers I don't know - I have not studied them to the same degree. The
reason why people tend to parenthesize where it is not needed is to
increase clarity. Quick - do these two mean the same:

	if ((a == 1 && b == 2) || (c == 3 && d == 4))
	
	if (a == 1 && b == 2 || c == 3 && d == 4)

In the first case, my intention is much clearer (to myself included).

I believe (as do many others) that parentheses serve a double function:
overriding the normal precedence of operators, AND making things readable.
-- 
	dg@lakart.UUCP - David Goodenough		+---+
							| +-+-+
	....... !harvard!cca!lakart!dg			+-+-+ |
						  	  +---+

sullivan@vsi.UUCP (Michael T Sullivan) (07/09/88)

In article <2550075@hpisod2.HP.COM>, decot@hpisod2.HP.COM (Dave Decot) writes:
> 
> Return is not a function call, and it shouldn't look like one.
> 
> > >	return(0);	/* one wonders why the () are there */
> > 
> > 1) Because it looks consistent.
> 
> With what?  Why do you want to make it easier to confuse function calls
> with statements that don't come back?

Like exit() or abort()???

> I see no reason to add further confusion by making flow control look like
> a function call.  I use "return e;" because it's less cluttered and more
> distinct.


When I have something like:

	return(a == b ? c : d);

I think it looks better than:

	return a == b ? c : d;

Maybe if return had a space between the paren like while, for, and switch
everybody would be happy (and there'd be peace in the world, and no more
smog, ...).  I think I'll try that for a while and see how it goes.

-- 
Michael Sullivan			{uunet|attmail}!vsi!sullivan
V-Systems, Inc.  Santa Ana, CA		sullivan@vsi.com
ons, workstations, workstations, workstations, workstations, workstations, work

nevin1@ihlpf.ATT.COM (00704a-Liber) (07/09/88)

In article <2550075@hpisod2.HP.COM> decot@hpisod2.HP.COM (Dave Decot) writes:

|> 3) The programmer has gotten used to putting parentheses around just about
|>    everything.

|That may be true in your case, but it's a bug in the language design.

If it is truly a bug, how would you propose fixing it?

|Parentheses are overloaded for all of the following distinct purposes:

|    function calls
|    if, while, and do-while statements
|    casts
|    type construction (used both to indicate functions and for grouping)
|    function declarations
|    evaluation order grouping

Since 'return' can return an expression, parentheses are always allowed
(but never required).  Does it really matter whether they are there or not?
Is it really any harder to understand a program that has them vs. one that
does not?

|I see no reason to add further confusion by making flow control look like
|a function call.  I use "return e;" because it's less cluttered and more
|distinct.

For the case of a constant or a single variable, I do too.  But on those
few occasions that I have to return an expression (instead of using a tmp
variable and returning that), I sometimes put parentheses around the
expression.

If it makes it easier to read, then put them in.  Otherwise, (as long as it
doesn't make it harder to read), it really shouldn't matter.
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				You are in a maze of little twisty
 /  / _ , __o  ____		 email paths, all different.
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

ado@elsie.UUCP (Arthur David Olson) (07/10/88)

I leave out the parentheses in a
	return whatever;
statement; this ensures that if I mistakenly write
	retunr whatever;
I'll get a warning at compile time--along with a line number--rather than
an "Undefined: _retunr" error at link time (with no indication of where the
error is) as would be true if I wrote
	retunr(whatever);
(which the compiler would take to be a function call.)

Of course this advice applies only to those of us who make mistakes.
-- 
	ado@ncifcrf.gov			ADO is a trademark of Ampex.

wes@obie.UUCP (Barnacle Wes) (07/10/88)

In article <2550075@hpisod2.HP.COM>, decot@hpisod2.HP.COM (Dave Decot) writes:
> I see no reason to add further confusion by making flow control look like
> a function call.  I use "return e;" because it's less cluttered and more
> distinct.

I agree.  I also try to make the flow-control statements that REQUIRE
parenthesis (if, while, & for) look different, too.  I always write
functions with the parentheses immediately following the name, i.e.
function(), and control statements with whitespace between the statment
and the parentheses, i.e. if (something) and while (braindead).
-- 
                     {hpda, uwmcsd1}!sp7040!obie!wes
           "Happiness lies in being priviledged to work hard for
           long hours in doing whatever you think is worth doing."
                         -- Robert A. Heinlein --

mdf@tut.cis.ohio-state.edu (Mark D. Freeman) (07/11/88)

In <2550075@hpisod2.HP.COM> decot@hpisod2.HP.COM (Dave Decot) writes:
>Return is a statement that modifies the default
>flow of control, such as:
>
>     goto label;		/* NOT goto(label); */
>     break;			/* NOT break();     */
>     continue;			/* NOT continue();  */
>
>Return is not a function call, and it shouldn't look like one.
>
>Why do you want to make it easier to confuse function calls
>with statements that don't come back?

What about exit()?  Does it require parenthesis?  How does it fit into
your argument?
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`
`




-- 
Mark D. Freeman						  (614) 262-1418
Applications Programmer, CompuServe	      mdf@tut.cis.ohio-state.edu
[70003,4277]			      ...!att!tut.cis.ohio-state.edu!mdf
Columbus, OH		      Guest account at The Ohio State University

henry@utzoo.uucp (Henry Spencer) (07/11/88)

> ... this is a weakness of RD parsers: the amount of
> work incurred by unnecessary parentheses is quite considerable, especially
> in a language such as C, with 15 levels of operator precedence....

Well, yes, *if* you implement the RD parser straight from the grammar and
do no optimization.  One can do better, at the price of greater complexity,
by explicitly looking for the simple cases.
-- 
Anyone who buys Wisconsin cheese is  |  Henry Spencer @ U of Toronto Zoology
a traitor to mankind.  --Pournelle   | {ihnp4,decvax,uunet!mnetor}!utzoo!henry

levy@ttrdc.UUCP (Daniel R. Levy) (07/11/88)

In article <17458@tut.cis.ohio-state.edu>, mdf@tut.cis.ohio-state.edu (Mark D. Freeman) writes:
> In <2550075@hpisod2.HP.COM> decot@hpisod2.HP.COM (Dave Decot) writes:
> >Return is a statement that modifies the default
> >flow of control, such as:
> >     goto label;		/* NOT goto(label); */
> >     break;			/* NOT break();     */
> >     continue;			/* NOT continue();  */
> >Return is not a function call, and it shouldn't look like one.
> >Why do you want to make it easier to confuse function calls
> >with statements that don't come back?
> What about exit()?  Does it require parenthesis?  How does it fit into
> your argument?

Butting in, I say:

exit() is a bona fide, real, genuine, honest-to-goodness FUNCTION CALL.
It just so happens that the usual effect of calling it (besides miscellaneous
cleanup actions, such as flushing any open stdio buffers) is to stop
execution of the program that called it.  Were you to feel a bit wild and
crazy some time, you could perfectly well write your own exit() which could
do whatever oddball things it wished and not stop the program at all when
called.  E.g.,

exit(i) int i; { printf("nyah nyah you tried to exit %d\n", i); }

"return" is DEFINED as stopping execution of the FUNCTION that called it
and returning control (and a value, if specified) to "whatever" called that
function, whether it was another function, or some veiled-from-view system
mechanism (as with main() or as an interrupt handler).
-- 
|------------Dan Levy------------|  THE OPINIONS EXPRESSED HEREIN ARE MINE ONLY
|    AT&T  Data Systems Group    |  AND ARE NOT TO BE IMPUTED TO AT&T.
|        Skokie, Illinois        | 
|-----Path:  att!ttbcad!levy-----|

jfh@rpp386.UUCP (John F. Haugh II) (07/12/88)

In article <1988Jul10.201845.27751@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
>> ... this is a weakness of RD parsers: the amount of
>> work incurred by unnecessary parentheses is quite considerable, especially
>> in a language such as C, with 15 levels of operator precedence....
>
>Well, yes, *if* you implement the RD parser straight from the grammar and
>do no optimization.  One can do better, at the price of greater complexity,
>by explicitly looking for the simple cases.

one of the major strengths of r-d parsers is you can code the parser
straight from the grammar.  performing the transformations from left to
right recursion should be fairly automatic and is the only really
worthwhile (ease of coding, speed and complexity tradeoffs being
considered) optimization i can see.

the geneal case of trying to reduce the recursion present in the parser
would seem to require a potentially arbitrary amount of look ahead, or
as a minimum, the same amount of lookahead as the length of the shortest
sentence the parser is trying to recognize.  clarifications, henry?

>Anyone who buys Wisconsin cheese is  |  Henry Spencer @ U of Toronto Zoology
>a traitor to mankind.  --Pournelle   | {ihnp4,decvax,uunet!mnetor}!utzoo!henry

and what the hell does this mean???

- john.
-- 
John F. Haugh II                 +--------- Cute Chocolate Quote ---------
HASA, "S" Division               | "USENET should not be confused with
UUCP:   killer!rpp386!jfh        |  something that matters, like CHOCOLATE"
DOMAIN: jfh@rpp386.uucp          |             -- with my apologizes

bill@proxftl.UUCP (T. William Wells) (07/13/88)

In article <8108@elsie.UUCP>, ado@elsie.UUCP (Arthur David Olson) writes:
> I leave out the parentheses in a
>       return whatever;
> statement; this ensures that if I mistakenly write
>       retunr whatever;
> I'll get a warning at compile time--along with a line number--rather than
> an "Undefined: _retunr" error at link time (with no indication of where the
> error is) as would be true if I wrote
>       retunr(whatever);
> (which the compiler would take to be a function call.)

This is the first non-esthetic reason I've seen for not putting
in the parentheses; I'd note that it does not always work,
consider: retunr (a+b)*c;. Oh, well, nobody said programming was
going to be trivial...

Just to add some data to the discussion, here is what we do.

    o No function call has a space after the function descriptor.

    o Every keyword except sizeof is always followed by a space,
      newline, or semicolon.

    o Sizeof is always formatted as if it were a function call.
      Actually, we code no space after the sizeof because it is
      a unary operator and we parenthesize for uniformity; this
      makes it look like a function call.

    o For purely Hysterical Raisons we always use parentheses
      around the expression.  I think we'd change except for
      inertia and the pain of reformatting all the code of a new
      version of a product.

My own opinion on the use of parentheses is that almost any
consistent style is better than no style at all.  The
differences between most styles is a matter of esthetics; one
may choose almost any style one pleases and be "right".

dmg@ssc-vax.UUCP (David Geary) (07/13/88)

In article <175@lakart.UUCP>, David Goodenough writes:

>
>	if ((a == 1 && b == 2) || (c == 3 && d == 4))
>	
>	if (a == 1 && b == 2 || c == 3 && d == 4)
>
>In the first case, my intention is much clearer (to myself included).
>
>I believe (as do many others) that parentheses serve a double function:
>overriding the normal precedence of operators, AND making things readable.

"Unnecessary" parenthesis are something I use all the time in macro
definitions, also.  Consider:

#define Square(x)  x*x
#define GetNextChar(c)  c = getchar()

main()
{
  int  x=2, i=0;
  char ch;
  char string[100];

  while(GetNextChar(ch) != '\n')
    string[i++] = ch;

  printf("Square of 3 is:  %d\n", Square(x+1));
  printf("String is %s\n", string);
}

1)  The string is never read in, because the while statement expands to:

    while(ch = getchar() != `\n`)

    != has precedence over =, so the character is read by getchar(), then
    it is compared to '\n'.  If the character was a newline, ch gets assigned
    the value 1, if the character was not a newline, then it gets assigned
    the value 0. (NULL ?? ;-))

2)  Square(x+1) expands to:  x+1*x+1 which is: x+x+1.  In our case, we get:
    Square of 3 is:  5.

The above two macros should have been written like:

#define Square(x)       (x)*(x)
#define GetNextChar(c)  (c = getchar())

And now, everything will work as expected.  The moral of the story is:

1)  I always put parenthesis around all tokens in macros.
2)  I always put parenthesis around the entire macro definition.

Sometimes, of course, the parenthesis are unnecessary, but it sure helps
eliminate some nasty bugs.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~	"...Raven hair and ruby lips,			~
~	 Sparks Fly from the fingertips..."		~
~							~
~		Witchy Woman, The Eagles		~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ David Geary, Boeing Aerospace,               ~ 
~ Seattle - "THE DRIZZLE CAPITAL OF THE WORLD" ~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

smryan@garth.UUCP (Steven Ryan) (07/14/88)

>the geneal case of trying to reduce the recursion present in the parser
>would seem to require a potentially arbitrary amount of look ahead, or
>as a minimum, the same amount of lookahead as the length of the shortest
>sentence the parser is trying to recognize.  clarifications, henry?

I'm not Henry, but .....

A context free grammar is union of Dyck set and a linear (regular expression)
grammar. The regular expression part of the grammar can be parsed with loops
and conditionals (actually just an FSM) and recursion isn't necessary. One of
the optimisations is to recognise linear parts of language and translate them
into your favorite version of an FSM.

C has three symbol pairs which form embedding constructs: () [] {}. [] can be
embedded in (), () in [], and () and [] in {} so that in general, some form of
stack is necessary. This can still be optimise some what by counting when ()
is directly embedded in (), [] in [], {} in {}, instead of stacking.

In something like
        ((a+b)+c[(d)])
the expression scanner can count the parentheses and only need recurse to
handle the subscript:
        ((a+b)+c[(d)])
  expr: 12   2       1
    subscript:  1   1
      expr:      1 1

Because on most machines, recursion is slower than looping, it is a tradeoff
between a more complicated or faster parser.
 
>>Anyone who buys Wisconsin cheese is  |  Henry Spencer @ U of Toronto Zoology
>>a traitor to mankind.  --Pournelle   | {ihnp4,decvax,uunet!mnetor}!utzoo!henry
>
>and what the hell does this mean???

Does anybody even try to understand?

                               Hafa an godne daege.
                                            sm ryan

news@ism780c.isc.com (News system) (07/14/88)

In article <5253@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704a-Liber,N.J.) writes:
>Since 'return' can return an expression, parentheses are always allowed
>(but never required).

This is not quite right.  A procedure may return a void expression.  But
parantheses may NOT enclose  a void experssion.  Thus statement:

     return ();

is malformed.  This is the reason that I chose not to use redundant parens
on returned expressions.

   Marv Rubinstein

nevin1@ihlpf.ATT.COM (00704a-Liber) (07/14/88)

In article <2089@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes:

>"Unnecessary" parenthesis are something I use all the time in macro
>definitions, also.

Most of the parentheses in macros ARE necessary as you have shown (but are
usually not sufficient as I will show).

>Consider:

>#define Square(x)  x*x

[David shows why this macro should be redefined as
#define	Square(x)	((x)*(x))
]

but consider the case where you try the following:

int	x;
x = 2;
(void)printf("The square of %d + 1 is %d.\n", x, Square(++x));

The Square macro does not work correctly because the argument has side
effects (this is why parentheses are not sufficient in macros).
-- 
 _ __			NEVIN J. LIBER	..!att!ihlpf!nevin1	(312) 510-6194
' )  )				You are in a little twisty maze of
 /  / _ , __o  ____		 email paths, all different.
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

karl@haddock.ISC.COM (Karl Heuer) (07/15/88)

In article <11925@ism780c.isc.com> marv@ism780.UUCP (Marvin Rubenstein) writes:
|In article <5253@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704a-Liber,N.J.) writes:
|>Since 'return' can return an expression, parentheses are always allowed
|>(but never required).
|
|This is not quite right.  A procedure may return a void expression.  But
|parantheses may NOT enclose  a void experssion.  Thus statement:
|     return ();
|is [syntactically] malformed.

This is not quite right either.  The empty string does not denote a void
expression.  A void function may not return a void expression, either with or
without the parens: "void f() { return exit(0); }" violates a constraint.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

paul@arthur.uchicago.edu (Paul Burchard) (07/21/88)

In article <2089@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes:
>"Unnecessary" parenthesis are something I use all the time in macro
>definitions, also.  Consider:
>
>#define Square(x)  x*x
>#define GetNextChar(c)  c = getchar()
>
  [...]
>The above two macros should have been written like:
>
>#define Square(x)       (x)*(x)
>#define GetNextChar(c)  (c = getchar())
>
  [...]
>~ David Geary, Boeing Aerospace,               ~ 
>~ Seattle - "THE DRIZZLE CAPITAL OF THE WORLD" ~


Actually, they should have been written like

	#define Square(x)       ((x)*(x))
	#define GetNextChar(c)  ((c) = getchar())

I trust you can imagine code that requires these further parens.


-----------------------------------------------------------------------------
Paul Burchard	paul@zaphod.UChicago.Edu
enum Chicago_weather { roast, freeze, steam, dry, simmer } today;
-----------------------------------------------------------------------------

steve@oakhill.UUCP (steve) (07/26/88)

I'm sorry I can't include the text I'm mentioning since I'm haveing net
reply problems, but I'll fake it as best I can.

In an absolute sense

>   #define square(x)    (x * x)

shouldn't be :

>   #define square(x)    ((x) * (x))

it should be :

>   #define square(x)    (temp = (x),(temp * temp))

in order to avoid problems with sending in a post incremented variable;


BUT, - as with everything else in C, either of the first two forms
are good if you're careful and know what you're doing.  Form 1 works
if you know you're sending in a simple variable.  Form 2 works
if you are not sending in an expression that changes the variable.
Form 3 is slower than the other two, but more conservative.

Use your best judgement - macros are dangerous thing if not used carefully
That is why C compilers have a -P option.

                                Your mooncalf - Steve

To: paul@zaphod.UChicago.Edu
Subject: Re: Unnecessary Parenthesis
Newsgroups: comp.lang.c
In-Reply-To: <441@kaon.uchicago.edu>
References: <2089@ssc-vax.UUCP>
Organization: Motorola Inc., Austin Tx.
Cc: 
Bcc: 


I'm sorry I can't include the text I'm mentioning but

>   #define square(x)    (x * x)

shouldn't be :

>   #define square(x)    ((x) * (x))

it should be :

>   #define square(x)    (temp = (x),(temp * temp))

in order to avoid problems with sending in a post incremented variable;


BUT, - as with everything else in C, either of the first two forms
are good if you're careful and know what you're doing.  Form 1 works
if you know you're sending in a simple variable.  Form 2 works
if you are not sending in an expression that changes the variable.
Form 3 is slower than the other two, but more conservative.

                                Your mooncalf - Steve
From steve  Mon Jul 25 13:54:49 1988
Return-Path: <steve>
Received: by devsys.com (3.2/SMI-3.2)
	id AA13794; Mon, 25 Jul 88 13:54:49 CDT
Date: Mon, 25 Jul 88 13:54:49 CDT
From: steve
Message-Id: <8807251854.AA13794@devsys.com>
To: paul@zaphod.UChicago.Edu
Subject: Re: Unnecessary Parenthesis
Newsgroups: comp.lang.c
In-Reply-To: <441@kaon.uchicago.edu>
References: <2089@ssc-vax.UUCP>
Organization: Motorola Inc., Austin Tx.
Cc: 


I'm sorry I can't include the text I'm mentioning but having sending
problems.  I'l try to fake it.

>   #define square(x)    (x * x)

shouldn't be :

>   #define square(x)    ((x) * (x))

it should be :

>   #define square(x)    (temp = (x),(temp * temp))

in order to avoid problems with sending in a post incremented variable;


BUT, - as with everything else in C, either of the first two forms
are good if you're careful and know what you're doing.  Form 1 works
if you know you're sending in a simple variable.  Form 2 works
if you are not sending in an expression that changes the variable.
Form 3 is slower than the other two, but more conservative.

                                Your mooncalf - Steve

To: paul@zaphod.UChicago.Edu
Subject: Re: Unnecessary Parenthesis
Newsgroups: comp.lang.c
In-Reply-To: <441@kaon.uchicago.edu>
References: <2089@ssc-vax.UUCP>
Organization: Motorola Inc., Austin Tx.
Cc: 
Bcc: 


I'm sorry I can't include the text I'm mentioning but

>   #define square(x)    (x * x)

shouldn't be :

>   #define square(x)    ((x) * (x))

it should be :

>   #define square(x)    (temp = (x),(temp * temp))

in order to avoid problems with sending in a post incremented variable;


BUT, - as with everything else in C, either of the first two forms
are good if you're careful and know what you're doing.  Form 1 works
if you know you're sending in a simple variable.  Form 2 works
if you are not sending in an expression that changes the variable.
Form 3 is slower than the other two, but more conservative.

                                Your mooncalf - Steve

To: paul@zaphod.UChicago.Edu
Subject: Re: Unnecessary Parenthesis
Newsgroups: comp.lang.c
In-Reply-To: <441@kaon.uchicago.edu>
References: <2089@ssc-vax.UUCP>
Organization: Motorola Inc., Austin Tx.
Cc: 
Bcc: 


I'm sorry I can't include the text I'm mentioning but having sending
problems.  I'l try to fake it.

>   #define square(x)    (x * x)

shouldn't be :

>   #define square(x)    ((x) * (x))

it should be :

>   #define square(x)    (temp = (x),(temp * temp))

in order to avoid problems with sending in a post incremented variable;


BUT, - as with everything else in C, either of the first two forms
are good if you're careful and know what you're doing.  Form 1 works
if you know you're sending in a simple variable.  Form 2 works
if you are not sending in an expression that changes the variable.
Form 3 is slower than the other two, but more conservative.

                                Your mooncalf - Steve

> Nothing I say is quoteable - so don't expect to see anything important here.

steve@oakhill.UUCP (steve) (07/26/88)

extremely sorry for the previous mail.  I'm not too go at this yet.
Be gentill - I'm new at this.

	   your - mooncalf - Steve

karzes@mfci.UUCP (Tom Karzes) (07/26/88)

In article <1401@devsys.oakhill.UUCP> steve@oakhill.UUCP (steve) writes:
}I'm sorry I can't include the text I'm mentioning since I'm haveing net
}reply problems, but I'll fake it as best I can.
}In an absolute sense
}>   #define square(x)    (x * x)
}shouldn't be :
}>   #define square(x)    ((x) * (x))
}it should be :
}>   #define square(x)    (temp = (x),(temp * temp))
}in order to avoid problems with sending in a post incremented variable;

This doesn't work in general in C for a number of reasons.  First, C is not
an expression language, so you can't declare temp to be local to the
expression.  This means it has to either be global or defined by the client
(and of course, this requires fixing its type, but I won't complain about
that).  Second, even if you could declare it locally, you'd have to be
careful about the name you used to avoid a name conflict with a variable
used in the expression for x.

sar@datcon.UUCP (Simon A Reap) (09/23/88)

(old discussion, but our News was gebustenbroken for yonks)
In article <1401@devsys.oakhill.UUCP> steve@oakhill.UUCP (steve) writes three
alternatives for the square(x) macro:

>>   #define square(x)    (x * x)
>>   #define square(x)    ((x) * (x))
>>   #define square(x)    (temp = (x),(temp * temp))
>
Please note, the third version is *dangerous*.  An expression such as:

    z = square(x) + square(y);

expands to:

    z = (temp = (x),(temp * temp)) + (temp = (y),(temp * temp));

which looks OK, but note that, although C guarantees to perform the
assignment (temp = (x)) before the multiplication (temp * temp) in each
expansion of square(x), but it does *not* guarantee to complete the
first expansion before it starts the second (or vice versa).  I have
seen at least 2 compilers which do the first assignment, then the second
assignment (to the same 'temp' variable), followed by the 2 multi-
plications, so you end up with the same value of 'temp' squared twice.

Does anyone know how to get round this problem?  Please!!
(it's been bugging us for months :-( )

-- 
Enjoy,
yerluvinunclesimon                Opinions are mine - I don't even have a cat
Reach me at sar@datcon.co.uk, or ...!mcvax!ukc!pyrltd!datcon!sar

gwyn@smoke.ARPA (Doug Gwyn ) (09/25/88)

In article <23@datcon.UUCP> sar@datcon.co.uk (Simon A Reap) writes:
>    z = square(x) + square(y);
>Does anyone know how to get round this problem?  Please!!

	z = x*x + y*y;