?

Log in

No account? Create an account
Ramblings Journals I Read Calendar The Dirt MegaZone's Waste of Time Older Older Newer Newer
Coder geeks - MegaZone's Safety Valve
The Ramblings of a Damaged Mind
zonereyrie
zonereyrie
Coder geeks
This question was sent out at work by a co-worker:
Solve this in your head: What does the following code display, and why?

<?php
$i = 1;
$i += $i++ + ++$i;
echo 'i=', $i;
?>

Bonus question: Is the result always the same in other programming languages (JavaScript, Java, C#, ...; provided the syntax is adapted to the host language :))? Why (not)?


Oh hell...

$i += $i++ + ++$i;

OK, First the pre-increment should run, making $i = 2. 2 += 2 + 2 is 6. Then the post-increment will run, making it 7.

I would *hope* the results are the same, since the rules of precedence are fairly universal. But I wouldn't be shocked to find out they aren't the same.

I've just got to check it out...

PHP: 7
Perl: 7
JavaScript: 5 ... 5? WTF?! (And I ran it in FireFox and IE - same result.)

I bet JavaScript does the pre-increment but doesn't update the other slots, which would make it 1 += 1 + 2 so it is 4, then post-increment would make it 5. That would explain it - but it doesn't make it any less stupid.

So, who wants to try it in other languages? ;-)

BTW, the perl and JavaScript I used:
$i = 1;
$i += $i++ + ++$i;
print "i=" . $i . "\n";

<script type="text/javascript">
$i = 1;
$i += $i++ + ++$i;
document.write("i=" + $i);
</script>

Tags: , ,
Current Location: 42.33821N 71.59212W
I am: geeky geeky
Current Media: quiet office

10 STDOUT || STDIN
Comments
mackys From: mackys Date: April 22nd, 2006 12:56 am (UTC) (Direct Link)
I don't know PHP well enough to say with certainty what operations take precedence over others, or how preincrement and postincrement work, or even how the interpreter may store variables internally. All of which could change the answer.

But for vanilla C, the game runs approximately as follows:


  1. i gets 1
  2. The pre-increment happens to i just before the "+=" line executes. So between the assignment line and the "+=" line, i becomes 2.
  3. The "+=" expression starts with i being 2, and thus evaluates to "i += 2 + 2;" which in turn expands out to "i = 2 + (2 + 2);". So i is now 6.
  4. The post-increment from the "+=" statement happens just after the line is executed. i is now 7.
  5. The program prints 7.


Here is the C translation, which when compiled under GCC on FreeBSD does indeed print "7".

#include <stdio.h>

int main(void)
{
  int i;

  i = 1;
  i += i++ + ++i;
  printf("i = %i\n", i);
  exit(0);
}
mackys From: mackys Date: April 22nd, 2006 01:08 am (UTC) (Direct Link)

Okay, now looking...

Looks like i got it right. w00t.

The JavaScript thing is funny. Interpreters are often strange like that...

This post reminds me of the "one minute programming problems" I saw mid-late last year. If you're looking for job interview questions (not to be taken too seriously) these might be amusing:

http://mackys.livejournal.com/245284.html
agthorr From: agthorr Date: April 22nd, 2006 12:57 am (UTC) (Direct Link)
I don't know about PHP, but I'm 99% certain that in the C the behavior is undefined (meaning it may vary from compiler to compiler or even change depending on whether you have optimizations turned on or not).

I suspect Javascript gets 5 by evaluating left-to-right like this:

$i += $i++ + ++$i;        // i = 1
$i = $i + $i++ + ++$i;    // i = 1
$i = 1 + $i++ + ++$i;     // i = 1
$i = 1 + 1 + ++$i;        // i = 2
$i = 1 + 1 + 3;           // i = 3
$i = 5;                   // i = 5
jarodrussell From: jarodrussell Date: April 22nd, 2006 01:12 am (UTC) (Direct Link)
I'm going to guess "No" because it would depend on how the compiler parsed trhe command -- left-to-right or right-to-left.

Now o go see what you said, and hopefully I'll learn something new!
sweh From: sweh Date: April 22nd, 2006 01:19 am (UTC) (Direct Link)
I thought this was undefined in C. Indeed gcc will moan if you use -Wall:
#include <stdio.h>

int main()
{
  int i;

  i=1;
  i += i++ + ++i;
  printf("%d\n",i);
  return(0);
}

% gcc -Wall test.c
test.c: In function `main':
test.c:8: warning: operation on `i' may be undefined
test.c:8: warning: operation on `i' may be undefined

In a similar way, "i=i++" or "i += i++" or "i += ++i"are also potentially undefined.

Of course I last read about this 13 or 14 years ago and so may be misremembering!
From: (Anonymous) Date: April 22nd, 2006 01:21 am (UTC) (Direct Link)
Actually, I think the post-increment runs before the +=, which still gives 7. The procedure is:

1. pre-increment: $i increments from 1 to 2;
2. evaluation of both addends: 2 + 2 = 4;
3. post-increment: $i increments from 2 to 3;
4. accumulate: add 4 to $i, to get $i = 7.

If we change $i++ to $i--, Perl gives 3, which agrees with this analysis; if $i-- was evaluated after everything else, it would give 5.

- clg

(I wandered over from the Eyrie boards, but don't post much there either.)
solipsistnation From: solipsistnation Date: April 22nd, 2006 01:28 am (UTC) (Direct Link)

It displays this.
flife From: flife Date: April 22nd, 2006 04:57 am (UTC) (Direct Link)

C# Version

using System;

public class Inky
{
public static void Main()
{
int i = 1;
i += i++ + ++i;
Console.WriteLine("i = " + i);
}
}

Output:
i = 5
Press any key to continue

!!!
mackys From: mackys Date: April 22nd, 2006 06:33 am (UTC) (Direct Link)

Java

public class IncTest {
    public static final void main(String[] args)
    {
        int i;

        i = 1;
        i += i++ + ++i;
        System.out.println("i = " + i);
    }
}


When run:

C:\temp\incjava>java IncTest
i = 5

C:\temp\incjava>


Looks like another case of strict left-to-right eval...
merle_ From: merle_ Date: April 22nd, 2006 08:21 pm (UTC) (Direct Link)
"JavaScript: 5 ... 5? WTF?!"

And that'd be why you don't write lame code like that. Make it obvious what's going to happen. Really, is there any need, within one expression, to both pre- and post- increment the same variable, and add the values to the same variable?

I would have guessed 6, personally. But I would have slapped that coder upside the head. If you have to "test it out" in various languages, then you're doing something wrong.
10 STDOUT || STDIN