views:

534

answers:

2

I though that I know this one... I had no clue.

This simple For loop:

Dim i As Integer
Dim n As Integer = 10
Dim s As Integer = 1

For i = 0 To n Step s
    Console.WriteLine(i)
Next

compiles into this (I put it through Refelctor, so it's easier to read). I couldn't even get what it does with all these bit-shifts:

Dim n As Integer = 10
Dim VB$t_i4$L1 As Integer = 1
Dim VB$t_i4$L0 As Integer = n
Dim i As Integer = 0
Do While (((VB$t_i4$L1 >> &H1F) Xor i) <= ((VB$t_i4$L1 >> &H1F) Xor VB$t_i4$L0))
    Console.WriteLine(i)
    i = (i + VB$t_i4$L1)
Loop

Why For loop is mutilated like this?

+6  A: 

Probably because it's the "generic way" to cover all cases. Remember that for/step/next can go in any direction with any sign on the increment.

You used parameters on both the increment and the end-bound. The compiler has no way to know if you are going to count up or down, and if th end-bound is higher or lower than the start bound.

My guess is this is a way to get code that will work whatever you put in n and s (just a guess, I'm too tired to try and see if that is the case).

Also it makes copies of the parameters to prevent outside interference (like changing s or n during the enumeration).

=== UPDATE ===

I doubt anybody is still watching that question but I came back to this nugget just for the sake of completeness, and because I had some time. What VB is doing is a bit sneaky. The bit shift of S basically creates an integer based on the sign of S (it copies the MSB of s, ending up with &hFFFFFFFF is S is negative and &h00000000 if S is positive).

XOR of an integer value with -1 is equivalent to (-value-1). XOR with 0 is obviously a NOP. So if s is negative, it reverses both values (the -1 cancel each other) to compare them, effectively reversing the order of comparison without the need or a conditional, and thus no jump in the program flow. If s is positive it just compares them.

so, for s<0 you end up with

while (-i-1)<=(-n-1) 
==> while -i <= -n
==> while i>=n

for s>0 you end up with

while i <= n

Takes me back to my 68k ASM days where such tricks where the everyday stuff (such as XOR.l D0,D0 because XORing a register with itself was faster than loading zero in it...) :p

Denis Troller
A: 

I guess the obvious answer is that a For Next loop can be written as a Do While loop and converting one to the other means you only have to implement one type of loop in the complier. I can see how this works but why it is done, I've no idea.

Swinders