开发者

Simple Confusing Loops and Variable working

In this question,I'm asking how the following snippets work, as it involves weird use of variable:

while (+(+i--)!=0)
{
    i-=i++;
}
console.log(i)开发者_StackOverflow;


Interesting problem... you've tagged it Java, JavaScript and C -- note that while these languages have the same syntax, this question involves very subtle semantics that may (I'm not sure) differ across languages.

Let's break it down:

+(+i--)

The -- postfix decrement operator is most tightly bound. So this is equivalent to +(+(i--)). That is therefore equivalent to the value of +(+i) (that is, i), but it also decrements i after taking the value. It compares the value with 0 to see if the loop should continue. Thus, while (+(+i--)!=0) is equivalent to the following:

while (i-- != 0)

Note that it also performs i-- at the end of the loop.

Inside the loop, I believe you have some undefined behaviour, at least in C, because you are referencing i on the right, and also updating i on the left -- I believe that C doesn't define which order to do that in. So your results will probably vary from compiler to compiler. Java, at least, is consistent, so I'll give the Java answer. i-=i++ is equivalent i = i - i++, which is equivalent to to reading all the values out of the expression, computing the result of the expression, applying the post-increment, and then assigning the result back. That is:

int t = i - i;    // Calculate the result of the expression "i - i++"
i++;              // Post-increment i
i = t;            // Store the result back

Clearly, this is the same as writing i = 0. So the body of the loop sets i to 0.

Thus, the loop executes just one time, setting i to 0. Then, it decrements i one more time on the next while loop, but fails the check because i (before decrementing) == 0.

Hence, the final answer is -1, no matter what the initial value for i is.

To put this all together and write an equivalent program:

while (i-- != 0)
{
    int t = i - i;
    i++;
    i = t;
}
console.log(i);

When I tried it in Java and JavaScript, that's what I got. For GCC (C compiler), it gives -1 only when i starts out as 0. If i starts out as anything else, it goes into an infinite loop.

That's because in GCC (not necessarily all C compilers), i-=i++ has a different meaning: it does the store back to i first, then does the post-increment. Therefore, it is equivalent to this:

int t = i - i;    // Calculate the result of the expression "i - i++"
i = t;            // Store the result back
i++;              // Post-increment i

That's equivalent to writing i = 1. Therefore, on the first iteration, it sets i to 1, and then on the loop, it checks whether i == 0, and it isn't, so it goes around again, always setting i to 1. This will never terminate, but for the special case where i starts out as 0; then it will always terminate the loop and decrement i (so you get -1).

Another C compiler may choose to act like Java instead. This shows that you should never write code which both assigns and postincrements the same variable: you never know what will happen!

Edit: I tried to be too clever using that for loop; that wasn't equivalent. Turned back into a while loop.


That's soooo wierd! (I love it)

first, you can forget about the +(+...) part, it's just like saying 1 + (+1) = 2.

i-- means i = i - 1. In your while condition, you test if i-- is different from 0. Note: the test is made on i != 0 and then i's value is changed. If you wanted to change its value before the test, you should have used --i instead.

As for the i -= i++, it's a very dumb way to say i = 0. You must read it from right to left: i = i + 1 and then i = i - i1 (whatever value of i you have, you'll end up with 0.

Simplier quivalent snippet:

while (i-- != 0) {
  i = 0;
}
console.log(i);

1 a -= b means a = a - b.


i -= i++ would mean a similar thing to i = i-i; i++ (if you make the -= explicit).

In a similar fashion, you can pull the side effect of i-- out of the loop condition by transforming while (foo(i--)) { ... } to while (foo(i)) { i--; ...} i--; (you need to put it both in the loop body and after the loop because, at the end, the condition will be false and the loop body will not be executed but execution continues after the while loop).


The while condition evaluation happens based on operator precedence. I have used explicit braces to help understand the evaluation:

(+(+(i--)) != 0) which is equivalent to using (i-- != 0) as the '+' are just unary operators.

The expression i -=i++; is equivalent to i = i - i++; where the LHS expression gets evaluated from left to right.

i = 4;
while (+(+i--)!=0)  //here i would be decremented once to 3.
{     
     i-=i++; // here i = 3 - 3 = 0; even though i has been incremented by 1 its value is set to 0 with this assignment
} 


This is very simple. And I think the only reason to code like this is a concept called "code obfucasion" or "code confusing". This way makes the code harder to read and debug, so that can prevent from reverse engineer your code :-)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜