dbenham wrote:I disagree with penpen and agree with jeb. Penpen is assuming FOR /L uses the same parsing rules as SET /A. You must remember that SET /A has its own rules that differ from all the other contexts.
No, i don't i also use the normal int32 behavior and assume that it may be bound to maximum.
dbenham wrote:I believe FOR /L is using the same parsing rules that I outlined for the IF command:
dbenham wrote:All three numeric notations employ a similar strategy: First ignore any leading negative sign and convert the number into an unsigned binary representation. Then apply any leading negative sign by taking the 2's compliment.
The big difference (from SET /A) is that overflow conditions no longer result in an error. Instead the maximum magnitude value is used. A positive overflow becomes 2147483647, and a negative overflow becomes -2147483648.
Here is my proof:
Code: Select all
C:\test>for /L %N in (999999999999999 -1 2147483645) do @echo %N
2147483647
2147483646
2147483645
C:\test>for /L %N in (-999999999999999 1 -2147483645) do @echo %N
-2147483648
-2147483647
-2147483646
-2147483645
C:\test>for /L %N in (0xFFFFFFFFFFFFF -1 0x7FFFFFFD) do @echo %N
2147483647
2147483646
2147483645
C:\test>for /L %N in (-0xFFFFFFFFFFFFF 1 -0x7FFFFFFD) do @echo %N
-2147483648
-2147483647
-2147483646
-2147483645
C:\test>for /L %N in (07777777777777777777777777 -1 017777777775) do @echo %N
2147483647
2147483646
2147483645
C:\test>for /L %N in (-07777777777777777777777777 1 -017777777775) do @echo %N
-2147483648
-2147483647
-2147483646
-2147483645
I used a similar proof above:
penpen wrote:Code: Select all
Z:\>for /l %M in (2147483648 1 2147483648) do ( echo %M & pause )
And in Addition i did used the special value 0x8000000 because of the reason, that it's two complements value is again 0x8000000, so it doesn't have any effect.
And if it is computed as you assume, then this should be the result of 0x80000000, -0x80000000:
First ignore any leading negative sign and convert the number into an unsigned binary representation: 0x80000000, 0x80000000.
Then apply any leading negative sign by taking the 2's compliment: 0x80000000, 0x80000000.
In addition even if it tranformed to an decimal interchange Format the result should be the same: as -0x80000000 ==
-(-2147483648)=2147483648.
And even if you aplly the bound to the Maximum value will not change this number.
So if you were right, then for loops i've given above should in all these case do the same:
penpen wrote:for /l %M in (2147483646 1 0x80000000) do ( echo %M & pause )
for /l %M in (2147483646 1 -0x80000000) do ( echo %M & pause )
But they have a different behavior, so what you have assumed above cannot be right.
And i've given above do not depend to any implementation:
(**) serves: counter <=(*) 2147483647, counter in { -2147483648, 2147483647 }
(*) serves:counter (<= 2147483647) <= 2147483648, counter in { -2147483648, 2147483647 } (convert to upper bound possible)
(***) serves: -2147483648 = 0x80000000 != -0x80000000 AND ((s/u)int32 arithmetic) 0x80000000 == -0x80000000 ==> (s/u)int32 arithmetic is not used here.
That -0x80000000 should be equal to 0x80000000 == -2147483648 can be seen here:
Code: Select all
Z:\>for /L %a in (-0x80000000, 1, 2147483647) do (echo %a & pause)
Z:\>(echo -2147483648 & pause)
-2147483648
Drücken Sie eine beliebige Taste . . .
Edit: I've just seen that 0x80000000 is clamped to 2147483647 on Win 7, so this behavior can be explained with clamping, too.
Edit2: Added "on Win 7" to the edit, as the XP 64 here (no patches for whatever reasons, not mine) behaves different.
Edit 3: With "this behavior" in Edit 1 i meant -0x80000000 != 0x80000000, but to be able to differ you need additional Information (at least one additional bit).
penpen