Link to home
Start Free TrialLog in
Avatar of ramnars
ramnars

asked on

operators precedence

char *z="testing";
      char arr[20];
      char *y=arr;
      
      while(*y++=*z++);
 
   printf("%s\n",arr);   // prints "testing"

Im having troubles understanding this code fragment.
when you say *z++, is not equivalent to saying ' take the content of where z is pointing to now , and increment it'?

why is this working correctly?
Avatar of Sjef Bosman
Sjef Bosman
Flag of France image

It's not the CONTENT of z that gets incremented, it's z itself, making it point to the next location. The increments are executed after the assignment.
Avatar of ramnars
ramnars

ASKER

Based on operator precedence, * (dereference) must be executed first right?
and also, why is increments executed AFTER assignment? the assignment operarot has more precedence.

Bear with me for silly questions
ASKER CERTIFIED SOLUTION
Avatar of PaulCaswell
PaulCaswell
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of ramnars

ASKER

Ok. Gotcha.
Is thre any specific reason why increment happens later. Is it due to right to left or some thing like that?
++ is not defined as an operator in my C-book. There is
    expression:
        ++ lvalue
        lvalue ++
        etc...

and
    lvalue:
        *expression

It cannot be explained using operator precedence, it's a language construction. It says:
    *y= *z;
    y++;
    z++
Paul, the original loop works! See pg 101 and pg 187 of the C Programming Language, K&R, 1987
Increment doesn't always happen later. You can use ++x to make it happen earlier. The reason that *y++=*z++ stops at the end of the string (after the terminating zero is copied) is because an assignment expression has the value that was copied.

Paul
But you stated that ...

> while(*y++=*z++);
>
> would become
>
> while((*y)++=(*z)++);
>
> because '*' binds more tightly than '++'.

Pls explain...
sjef,

>>Paul, the original loop works! See pg 101 and pg 187 of the C Programming Language, K&R, 1987

It does indeed work .. sorry if my comment implied that it doesnt. I was exploding the loop into a form that might more clearly demonstrate its functionality.

>>Pls explain...

I was demonstrating what the compiler would do first because "OPerator precedence can be seen as the compiler automatically inserting brackets for you."

Paul
Indeed it did, for
    while(*y++ = *z++);
must have been something like
    while(*(y++)= *(z++));

and the (postfixed) increments are executed after the whole statement. See also pp 214-215 of the same book, both * and ++ as unary operators without any indicated precedence. The exact moment of incrementing the variables is not defined, which makes
    a[i++]= b[i++]
a dangerous operation.
sjef,

I'll quote K&R:

The unary operators * and & bind more tightly than arithmetic operators, so the assignment
y = *ip + 1
takes whatever ip points at, adds 1, and assigns the result to y, while
*ip += 1
increments what ip points to, as do
++*ip
and
(*ip)++
The parentheses are necessary in this last example; without them, the expression would
increment ip instead of what it points to, because unary operators like * and ++ associate right
to left.

Not clear but also not ambiguous. I dont think this is helping ramnars. Lets take this up elsewhere.

Paul
Agreed, it's getting theoretical. And I still don't agree (++ and -- are unary, not arithmetic operators).

Let's meet behind the church, 06:00 tomorrow. Weapons your choice. ;)
sjef,

I can make church. It makes me hot. How about the bike sheds? Weapons; I choose stress balls.

Paul
Bike sheds? Too many courting youngsters around, and I hate a disrespectful public. Stress balls are okay, though. The good old blunt object. Eh, filled with sand, rice, foam or led? And bring some gorgeous nurses, please?

Where do the operators come in, by the way? And who has precedence?
Postfix ++ and -- do not increment/decrement the lvalue until a sequence point is met and the expression has been therefore evaluated. I do not know where this is stated (pointers welcome), but ++ must bind closer, in this case, than the unary * because otherwise the code wouldn't work:

*y++=*z++;
is equivalent to
*(y++) = *(z++);

Since there is no sequence point within this expression, we know that the two sequence points are before the beginning and after the end of the expression. Therefore (y++) and (z++) evaluate to y and z respectively, the unary * operators get the chars at y and z respectively, set one equal to the other, and then after the full expression is evaluated and the ; (or the end of the while condition) is met, the values of y and z are incremented.

(*y)++ = (*z)++; would obviously not work in the other hand, since (*y)++ is not a legal lvalue.
(It is also obvious from the fact that the pointer values would never get updated)
About the part I said I didn't know:
I think "right-to-left associativity" means that for " $%x " where x is a variable and $ and % are operators, % is used before $, as well as that if any of the operators happen to be on the right-hand side, they are used before the left-hand side ones.
Please correct me.
Seems all okay to me. That sequence point of yours is another undefined thing in the C language and therefore another source of interesting problems.

int i= 4;
printf("%d\n", i++ + i++);
printf("%d\n", ++i + ++i);

What's to be the outcome of the expression in both occasions is not defined. Different compilers may produce different results. Oh well, that should be a different question in this TA...
Actually, I think the two expressions cause an undefined behaviour. Theoretically, small nazal demons may fly out of your nose :).

I think sequence points are well-defined somewhere in the language specification. Unfortunately, I have no access to it and the resources I have access to either don't mention it or mention it in passing. Anyhow, they should be studied especially before using the postfix ++/-- operators. For anyone who might be interested, this is where the C-FAQ at www.faqs.org says sequence points are put:
&&, ||, the comma operator and the ? part of the ternary ?: operator.