[comp.lang.c] Associativity -- what is it?

pjh@mccc.UUCP (Peter J. Holsberg) (02/18/88)

I find that associativity is a *very* difficult thing for me to explain,
undoubtedly because I don't understand it!  Would someone come to my
rescue?  Here's an example (assume that everything's been declared
correctly):

	x = 3 * i ++;

Book says that ++ has a higher precedence than *, and that ++
associates from R->L.  That makes me think that ++ should be applied
first, but I know it isn't.  But ????

Also, what does K&R say about these:
	--- a;
	- -- a;
	-- - a;
and
	---a;
	- --a;
	-- -a;


Thanks.

-- 
Peter Holsberg                  UUCP: {rutgers!}princeton!mccc!pjh
Technology Division             CompuServe: 70240,334
Mercer College                  GEnie: PJHOLSBERG
Trenton, NJ 08690               Voice: 1-609-586-4800

scjones@sdrc.UUCP (Larry Jones) (02/21/88)

In article <226@mccc.UUCP>, pjh@mccc.UUCP (Peter J. Holsberg) writes:
> 
> I find that associativity is a *very* difficult thing for me to explain,
> undoubtedly because I don't understand it!  Would someone come to my
> rescue?  Here's an example (assume that everything's been declared
> correctly):
> 
> 	x = 3 * i ++;
> 
> Book says that ++ has a higher precedence than *, and that ++
> associates from R->L.  That makes me think that ++ should be applied
> first, but I know it isn't.  But ????

But ++ IS applied first!  The key point here is that the RESULT of postfix
++ is the value BEFORE incrementation, not that postfix ++ is somehow deferred
until later.

It seems that you are confusing precedence and associativity.  Precedence is
used to specify the priority of DIFFERENT operators -- since multiplication
has higher precedence that addition the expression A * B + C is interpreted
as (A * B) + C.  Associativity is used to specify the priority of operators
with the SAME PRECEDENCE -- since subtraction associates left to right the
expression A - B - C is interpreted as (A - B) - C rather than A - (B - C).

> Also, what does K&R say about these:
> 	--- a;

K&R says that tokens are always the longest string which could be a vaild
token so this is interpreted as --(-a) which is invalid since -- can only
be applied to an lvalue (which -a is not).  This has nothing to do with
precedence or associativity - the innermost operator MUST be evaluated
first, since the outer operator has no operand until it is.

> 	- -- a;

Interpreted as -(--a).  Again this has nothing to do with precedence or
associativity.

> 	-- - a;

Same as your first example.

----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                MAIL: 2000 Eastman Dr., Milford, OH  45150
                                    AT&T: (513) 576-2070
"When all else fails, read the directions."

pjh@mccc.UUCP (Peter J. Holsberg) (02/23/88)

In article <224@sdrc.UUCP> scjones@sdrc.UUCP (Larry Jones) writes:
|In article <226@mccc.UUCP>, pjh@mccc.UUCP (Peter J. Holsberg) writes:
|> 
|> I find that associativity is a *very* difficult thing for me to explain,
|> undoubtedly because I don't understand it!  Would someone come to my
|> rescue?  Here's an example (assume that everything's been declared
|> correctly):
|> 
|> 	x = 3 * i ++;
|> 
|> Book says that ++ has a higher precedence than *, and that ++
|> associates from R->L.  That makes me think that ++ should be applied
|> first, but I know it isn't.  But ????
|
|But ++ IS applied first!  The key point here is that the RESULT of postfix
                                                          ^^^^^^^^^^^^^^^^^
|++ is the value BEFORE incrementation, not that postfix ++ is somehow deferred
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|until later.

Well, that still leaves me confused.  If i has the value 7, it is 7 that
is added to 3, so it seems to be that the ++ *is* deferred until later. 
Also, ++ has higher precedence than +, so why is the incrementation
delayed until after the current value of i is used?
 
I think we're getting close, though.  :-)  Thanks for the help.

-- 
Peter Holsberg                  UUCP: {rutgers!}princeton!mccc!pjh
Technology Division             CompuServe: 70240,334
Mercer College                  GEnie: PJHOLSBERG
Trenton, NJ 08690               Voice: 1-609-586-4800

edw@IUS1.CS.CMU.EDU (Eddie Wyatt) (02/23/88)

> 
> Well, that still leaves me confused.  If i has the value 7, it is 7 that
> is added to 3, so it seems to be that the ++ *is* deferred until later. 
> Also, ++ has higher precedence than +, so why is the incrementation
> delayed until after the current value of i is used?
>  
> I think we're getting close, though.  :-)  Thanks for the help.

  This really doesn't need a net rely, but ....

  You're having a problem understanding the semantic behind the post
increment instruction.  Think of it this way.

		a = 9 * i++;

is equivalent to

		a = 9 * f(&i);

		int f(x)
		    int *x;
		    {
		    int y;

		    y = *x;
		    *x = *x + 1;
		    return(y);
		    }

and
		a = 9 * ++i;

is equivalent to

		a = 9 * g(&i);

		int g(x)
		    int *x;
		    {
		    int y;

		    *x = *x + 1;
		    y = *x;
		    return(y);
		    }

   Note that i++ evaluates (returns) the value of i before incrementing and
   ++i evaluates (returns) the value of i after incrementing, that's all.

-- 

Eddie Wyatt 				e-mail: edw@ius1.cs.cmu.edu

scjones@sdrc.UUCP (Larry Jones) (02/24/88)

In article <234@mccc.UUCP>, pjh@mccc.UUCP (Peter J. Holsberg) writes:
> In article <224@sdrc.UUCP> scjones@sdrc.UUCP (Larry Jones) writes:
> |In article <226@mccc.UUCP>, pjh@mccc.UUCP (Peter J. Holsberg) writes:
> |> 
> |> I find that associativity is a *very* difficult thing for me to explain,
> |> undoubtedly because I don't understand it!  Would someone come to my
> |> rescue?  Here's an example (assume that everything's been declared
> |> correctly):
> |> 
> |> 	x = 3 * i ++;
> |> 
> |> Book says that ++ has a higher precedence than *, and that ++
> |> associates from R->L.  That makes me think that ++ should be applied
> |> first, but I know it isn't.  But ????
> |
> |But ++ IS applied first!  The key point here is that the RESULT of postfix
>                                                           ^^^^^^^^^^^^^^^^^
> |++ is the value BEFORE incrementation, not that postfix ++ is somehow deferred
>  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> |until later.
> 
> Well, that still leaves me confused.  If i has the value 7, it is 7 that
> is added to 3, so it seems to be that the ++ *is* deferred until later. 
> Also, ++ has higher precedence than +, so why is the incrementation
> delayed until after the current value of i is used?

The result of i++ is the value of i.  In addition, i gets incremented.  You
can think of i++ as being like inc(&i) where inc() is defined as:

   int inc(ip)
      int *ip;
      {
      int j = *i;
      *i = *i + 1;
      return j;
      }

So, it's not the ++ operator that's defered, it's the side effect of the
incrementation.  You should also be aware that the incrementation can be
defered for a long time - it may not happen until after the assignment.
That's why i = i++ + 2; has no defined value -- you don't know whether the
incrementation is done before or after the assignment.

> I think we're getting close, though.  :-)  Thanks for the help.

Hope this clears it up for good.

----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                MAIL: 2000 Eastman Dr., Milford, OH  45150
                                    AT&T: (513) 576-2070
"When all else fails, read the directions."

bc@halley.UUCP (Bill Crews) (02/24/88)

In article <234@mccc.UUCP> pjh@mccc.UUCP (Peter J. Holsberg) writes:
>In article <224@sdrc.UUCP> scjones@sdrc.UUCP (Larry Jones) writes:
>|In article <226@mccc.UUCP>, pjh@mccc.UUCP (Peter J. Holsberg) writes:
>|> 
>|> 	x = 3 * i ++;
>|> 
>|> Book says that ++ has a higher precedence than *, and that ++
>|> associates from R->L.  That makes me think that ++ should be applied
>|> first, but I know it isn't.  But ????
>|
>|But ++ IS applied first!  The key point here is that the RESULT of postfix
>                                                          ^^^^^^^^^^^^^^^^^
>|++ is the value BEFORE incrementation, not that postfix ++ is somehow deferred
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>|until later.
>
>Well, that still leaves me confused.  If i has the value 7, it is 7 that
>is added to 3, so it seems to be that the ++ *is* deferred until later. 
>Also, ++ has higher precedence than +, so why is the incrementation
>delayed until after the current value of i is used?

Here is how to think of it.  ++ performs two functions.  It returns a value,
and it has an effect on the variable to which it is applied.

If the ++ precedes its operand:

	it increments the operand
	it returns the resulting value

If the ++ succeeds its operand:

	it increments the operand
	it returns the value of the operand prior to the increment

The other operators with which you are comparing it have only the functions of
returning a value.  This makes it confusing.  But the act of returning the
previous value is quite different from deferring the operator's effect.

-bc
-- 
Bill Crews                                   Tandem Computers
bc@halley.UUCP                               Austin, Texas
..!rutgers!im4u!halley!bc                    (512) 244-8350

jfh@killer.UUCP (The Beach Bum) (02/24/88)

In article <234@mccc.UUCP> pjh@mccc.UUCP (Peter J. Holsberg) writes:

[ one explaination down, twenty five more to go ;-) ]

>Well, that still leaves me confused.  If i has the value 7, it is 7 that
>is added to 3, so it seems to be that the ++ *is* deferred until later. 
>Also, ++ has higher precedence than +, so why is the incrementation
>delayed until after the current value of i is used?
> 
>I think we're getting close, though.  :-)  Thanks for the help.
>-- 
>Peter Holsberg                  UUCP: {rutgers!}princeton!mccc!pjh

This comes from a discussion which I believe was given in the document
explaining the implementation of the portable C compiler.

Consider ++ in it's two forms as a short-hand notation (don't believe
it's true, just consider it.  Flames to /dev/null) for:

pre-fix:	++ X	->	(X = X + 1)
post-fix:	X ++	->	((X = X + 1), X - 1)

So, the increment gets done, but, the value you get has been `adjusted'
if you will.

Try this:
		x = 5;
		printf ("3 * x ++ = %d\n", 3 * x ++);
		printf ("now x = %d\n", x);

You should get 15 and 4.  I suspect you expected 18 or 16 or something
like that.

[ I believe the context was that the compiler generated the trees using
  the long-hand, and then hoped to optimize to using increment instructions
  later. ]

- John.
-- 
John F. Haugh II                  SNAIL:  HECI Exploration Co. Inc.
UUCP: ...!ihnp4!killer!jfh                11910 Greenville Ave, Suite 600
"You can't threaten us, we're             Dallas, TX. 75243
  the Oil Company!"                       (214) 231-0993 Ext 260

dmt@ptsfa.UUCP (Dave Turner) (02/25/88)

In article <3466@killer.UUCP> jfh@killer.UUCP (The Beach Bum) writes:
>In article <234@mccc.UUCP> pjh@mccc.UUCP (Peter J. Holsberg) writes:
>
>
>pre-fix:	++ X	->	(X = X + 1)
>post-fix:	X ++	->	((X = X + 1), X - 1)
>
>Try this:
>		x = 5;
>		printf ("3 * x ++ = %d\n", 3 * x ++);
>		printf ("now x = %d\n", x);
>
>You should get 15 and 4.  I suspect you expected 18 or 16 or something
>like that.
>


I expected to get 15 and 6 (not 4) which is exactly what I got when I tried it.

I've always found it to be useful to look at ++x and x++ and say:

	++x	increment x before using it in another expression in the
		same statement

and

	x++	use the present value of x in any other expressions in this
		statement before incrementing x.
		X in the next statement will have the new value.

There's more to be said but the above has been satisfactory for over 11 years.


-- 
Dave Turner	415/542-1299	{ihnp4,lll-crg,qantel,pyramid}!ptsfa!dmt

cory@upba.UUCP (02/26/88)

(Sorry for posting instead of mailing, I couldn't find a path to mccc)

> 	x = 3 * i ++;
> 
> Book says that ++ has a higher precedence than *, and that ++
> associates from R->L.  That makes me think that ++ should be applied
> first, but I know it isn't.  But ????

I can't really give you an understanding of associativity, as I don't know
what you are missunderstanding.  I could quote the definition, but I don't
think that would solve your problem.  I CAN try to help you understand the
concept of precedence in expression evaluations.  You seem to be confused
on the use of "var ++".  First, think of precedence as just putting a lot
of parentheses everywhere.  You know that ++ has a higher precedence than
*, so lets rewrite your example with parentheses to show the precedence:
	 	x = ( 3 * ( i ++ ) );
Now lets evaluate the expression as it is written.  First the inner-most
parentheses are evaluated:
	EXP=	( i ++ )
This reads "get the value of i, increment i, and return the pre-increment
value".  The value of this part of the expression is the before-increment
value of i.  Now lets continue to the next level of parentheses:
	EXP=	( 3 * EXP )
This says multiply 3 times the value of the inner expression. (which was
the pre-increment value of i)  Finally:
	 	x = ( 3 * ( i ++ ) );
increments i by 1 unit of i's variable type and then assigns x the value
of 3 times the pre-increment value of i. (guzzuntite)

Hope this has been some help.

					-Cory

...!ihnp4!upba!cory (Cory Dekker @ United Phone Book Advertisers)| DISCLAIMER:
Work: 1221 N St, Suite #800; Lincoln, NE 68508 {Ph: 402-476-2200}| My posting..
Home: 800 Foxcroft Ct, #188; Lincoln, NE 68510 {Ph: 402-483-7761}| MY opinions!

pjh@mccc.UUCP (Peter J. Holsberg) (02/26/88)

In article <230@sdrc.UUCP> scjones@sdrc.UUCP (Larry Jones) writes:
|In article <234@mccc.UUCP>, pjh@mccc.UUCP (Peter J. Holsberg) writes:
|> In article <224@sdrc.UUCP> scjones@sdrc.UUCP (Larry Jones) writes:
|> |In article <226@mccc.UUCP>, pjh@mccc.UUCP (Peter J. Holsberg) writes:
|> |> 
|> |> 	x = 3 * i ++;
|> |> 
|> |> Book says that ++ has a higher precedence than *, and that ++
|> |> associates from R->L.  That makes me think that ++ should be applied
|> |> first, but I know it isn't.  But ????
|> |
|> |But ++ IS applied first!  The key point here is that the RESULT of postfix
|>                                                           ^^^^^^^^^^^^^^^^^
|> |++ is the value BEFORE incrementation, not that postfix ++ is somehow deferred
|>  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|> |until later.
|> 
|> Well, that still leaves me confused.  If i has the value 7, it is 7 that
|> is added to 3, so it seems to be that the ++ *is* deferred until later. 
|> Also, ++ has higher precedence than +, so why is the incrementation
|> delayed until after the current value of i is used?
|
|The result of i++ is the value of i.  In addition, i gets incremented.  You
|can think of i++ as being like inc(&i) where inc() is defined as:
|
|   int inc(ip)
|      int *ip;
|      {
|      int j = *i;
|      *i = *i + 1;
|      return j;
|      }
|
|So, it's not the ++ operator that's defered, it's the side effect of the
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|incrementation.  You should also be aware that the incrementation can be
|defered for a long time - it may not happen until after the assignment.
|That's why i = i++ + 2; has no defined value -- you don't know whether the
|incrementation is done before or after the assignment.
|
???? Then what does the ++ operator-sans-side effect actually do???  It
looks like it does nothing.

-- 
Peter Holsberg                  UUCP: {rutgers!}princeton!mccc!pjh
Technology Division             CompuServe: 70240,334
Mercer College                  GEnie: PJHOLSBERG
Trenton, NJ 08690               Voice: 1-609-586-4800

pjh@mccc.UUCP (Peter J. Holsberg) (02/26/88)

Dave,

Your clear English-language statements reflect exactly the way I learned
it, too.
-- 
Peter Holsberg                  UUCP: {rutgers!}princeton!mccc!pjh
Technology Division             CompuServe: 70240,334
Mercer College                  GEnie: PJHOLSBERG
Trenton, NJ 08690               Voice: 1-609-586-4800

al@gtx.com (0732) (02/26/88)

In article <4140@ptsfa.UUCP> dmt@ptsfa.UUCP (Dave Turner) writes:
 
>I've always found it to be useful to look at ++x and x++ and say:
>
>	x++	use the present value of x in any other expressions in this
>		statement before incrementing x.

I hate to keep beating this horse, but the above statement is false.
just see K&R p. 50.

The problem the original questioner had [ essentially, "in a+b++ why
does the addition appear to be done before the incrementation when the
incrementation has higher priority?"] is just due to a confusion of
syntax with semantics.  syntactically, the ++ has higher priority and
IS "applied" first.  However, the semantics of applying ++ are defined
in such a way as to defer the side effect.  (exactly how long to defer
the side effect is not well defined.)

    ----------------------------------------------------------------------
   | Alan Filipski, GTX Corp, 2501 W. Dunlap, Phoenix, Arizona 85021, USA |
   | {ihnp4,cbosgd,decvax,hplabs,amdahl}!sun!sunburn!gtx!al (602)870-1696 |
    ----------------------------------------------------------------------

mike@arizona.edu (Mike Coffin) (02/27/88)

A simple way to understand the postincrement operator is to note that
(x++) is equivalent to ((x += 1) - 1).
-- 

Mike Coffin				mike@arizona.edu
Univ. of Ariz. Dept. of Comp. Sci.	{allegra,cmcl2,ihnp4}!arizona!mike
Tucson, AZ  85721			(602)621-4252