Bite my bytes

What I learn by day I blog at night - A blog from Microsoft Consultant working from Ljubljana, Slovenia

  Home :: Contact :: Syndication  
  999 Posts :: 7691 Comments :: 235 Trackbacks

Search

Most popular posts

Categories

My Projects

Archives

Stuff


Copyright © by David Vidmar
 
Contact me!
 
LinkedIn Profile
 
 
 

Igor showed me a really nice coding riddle. If you know this one, forget it, but if you don't, try to honestly answer what result you expect. 

1int i = 3;
2i += i++;
3
4Console.WriteLine(i);

Only after that try compiling the code (I suggest you use SnippetCompiler) and verify the result. If you are like me and most of my co-workers, your answer was wrong. Right?

You can play with ILDASM to look at the low level MSIL code and you will see what happens. Also take a look at the compiled code with Reflector.

Also you might want to take a look at this variant.

1int i = 3;
2i += ++i;
3
4Console.WriteLine(i);

Igor found this on some blog but we couldn't find the post. Google is quite usfull when searching for "i += i++"!
If you know the source of this, please let me know!

Posted on Thursday, March 03, 2005 5:50 PM | Filed under: Developement |

Feedback

# re: += ++ riddle 3/4/2005 9:28 AM Miha Markič [MVP C#]
Hecno, ja.

# re: += ++ riddle 3/5/2005 2:27 PM Tadej
It's obvious, isn't it? ;-)

i = 3;
Ok, let's put 3 into box labeled 'i';

i += i++
Uh, I'l need to add something to i. Let's push i (which has
value of 3) on the stack.
i++
Aha, I need to push the contents of i (which is still 3) and
then increase i for one (now i has the value of 4, I suppose).
Now I finally have two numbers on the stack, waiting to be
added. Aha, 3 + 3 = 6.
Assign 6 to i and thus overwrite 4.

I admit I came up with 7 the first time.. :-)

Just of curiosity, was the value of i really 4 during the course of calculation? I mean if I we had:
static int i = 3;
and
the program is running several threads on a multiprocessor
machine
and
the context switch occurs right after i++ evaluates

Would then one thread end up with 6 and the other 8?

This riddle also reminds me of a bug my collegues were looking at a couple of weeks ago. The code snippet was like:

OnCreateNewVersion()
{
// blahblah
int newVersion = document.Version++;
}

The question was: Why the newVersion equals the old one, even though the document.Version was increased?

# re: += ++ riddle 3/5/2005 3:43 PM Mare
Tadej, it sure ain't that obvious. I mean, it's obvious in C/C++ and Java, but not in C#.

Type int is a class type in C# and one would expect that all the operations are performed on refereces not on the values.

However compiler operates with references only when necessary, otherwise it sticks with values. I guess, this is a performance/backward compability issue.

It somehow resembles strings handeling in .NET (new instance on every operation).


# re: += ++ riddle 3/5/2005 6:13 PM Tadej
Mare, I am sorry if you got the impression that it was really obvious. I did put two smileys into my post and I admitted I was wrong the first time when I tried it. So - no it was not that obvious.

However, int is a value type in C# (actually in all .NET languages), since it is derived from the System.ValueType.

I did some moe thinking and came to conclusion, that the result is actually determined by the definition of operators and the rules for expression evaluation.

The operator += is defined in the following way:

x += y -> x = x + y

With this in mind, the behavior no longer depends on an argument being a value/reference type.
If you rewrite the expression you get

i = i + i++

Taking into account the definition of x++ (return x and then increase it by one) becomes more clear that the result is two times the value of i. In this way one could say that ++ operator behaves similar as an operation on a string (creating a new instance).

On the other hand, if you write

i = i++ + i

you get 7 as a result, because the expressions are being evaluated from left to right. So in a sense the operations actually are performed on a reference.


# re: += ++ riddle 3/5/2005 6:32 PM Mare
> However, int is a value type in C# (actually in all .NET languages), since it is derived from the System.ValueType.

Yeah, but it's DERIVED from a class :)
It's not a "normal" type as we know in other languages.

As I stated before: compiler obviously handles objects that are instances of a ValueType as values. It handles them as normal objects only when needed (e.g. 5.ToString() comes to mind)

# re: += ++ riddle 3/5/2005 7:40 PM Tadej
> Yeah, but it's DERIVED from a class :)
Technically not :-)

If you write:
class TheValueType : System.ValueType { int i; }

compiler will object.

You'll need to write:
struct TheValueType { int i; }

which is actually translated into MSIL as:
extends [mscorlib]System.ValueType

So class-es are something living in a managed heap and struct-s live on stack. In this sense I agree with yours "not a normal type" - a struct is not a class, but it is a type.

Since struct may have also a function, 5.ToString() does not mean that .NET handles int as a "normal" object. However .NET does allow:

int i = 12;
object o = i;
i = 21;
Console.Writeline("i: {0}, o: {1}", i, o);

resulting in i: 21, o: 12

But this bring us to (un)boxing which is another topic.


# re: += ++ riddle 3/6/2005 7:29 PM David
I don't see how could and operation like ++ work by reference not by value. And simple glanse at C# documentation revelas that Int is not a class but struct.

I believe the confusing situation is most easliy explained by "result of x++ or x-- is the value of x before the operation". ++ is just a function that returns a value, right?

So we could write it i = i + ValuePlusPlus(i);

ValuePlusPlus() is my imaginary function that returs the value i and then increments the i.

I tried to find an implementation of ++ operator in Reflector, but with no success.

# re: += ++ riddle 3/6/2005 10:20 PM Igor
Original post: http://weblogs.asp.net/lucabol/archive/2004/08/31/223580.aspx

# re: += ++ riddle 3/7/2005 9:22 AM Mare
> I don't see how could and operation like ++ work by reference not by value.

Why not? It's just a matter of an operator definition, not a matter of common sense understanding. One could easly overload the ++ operator to work on any type of object with anykind of operation (let's say changing the color of a button).

I guess, the lesson learnd (at least for me) is: the only real object language is SmallTalk. If I have only knew this before, I wouldn't complicate so much :)





# re: += ++ riddle 3/11/2005 2:31 PM MarkoD
I tried this in Linux in C first and it returned i = 7.
Then David tried it in C++ in windows and the result is also i = 7;

We disassemled the executables:

C - linux (this one is wierd, if anyone can explain, go ahead):

pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl %ebp, %esp
popl %ebp


c++

i += i++;
0040101B mov eax,dword ptr [i]
0040101E add eax,dword ptr [i]
00401021 mov dword ptr [i],eax
00401024 mov ecx,dword ptr [i]
00401027 add ecx,1
0040102A mov dword ptr [i],ecx

managed c++

i += i++;
0000000c add esi,esi
0000000e inc esi

c# (which returns i = 6):

00000015 mov dword ptr [ebp-10h],esi
00000018 mov ebx,esi
0000001a inc esi
0000001b mov eax,dword ptr [ebp-10h]
0000001e add eax,ebx
00000020 mov esi,eax

I also tried java in linux:

import java.*;

public class Test {

public Test(){}

public static void main(String[] args) {
int i = 3;
i += i++;
System.out.println(i);
}

}

The result is i = 6, like C#. Here's the disassembly:

public class Test extends java.lang.Object{
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return

public static void main(java.lang.String[]);
Code:
0: iconst_3
1: istore_1
2: iload_1
3: iload_1
4: iinc 1, 1
7: iadd
8: istore_1
9: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
12: iload_1
13: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
16: return

}

# re: += ++ riddle 3/11/2005 4:15 PM Igor
JavaScript rulez!! Function

function Test() {
var i = 3;
i += i++;
alert(i);
}

returns 6.

# re: += ++ riddle 3/14/2005 5:09 PM Mare
This has violentlly killed my valuetype/reference theory :)


Comments have been closed on this topic.