In versions 5.71 and 5.70 of the 64-bit Windows editions of PureBasic, a negative longword constant which is defined via hexadecimal notation is treated as a (positive) quadword (that is, as an "integer" on the platform). This can cause significant confusion!! For example:
EnableExplicit
#MyConstant = $81010000
#MyConstantB = -2130640896 ;(same value in decimal notation)
Define.l ThsLng
ThsLng = #MyConstant
If (ThsLng = #MyConstant)
Debug "Correct behavior."
Else
Debug "Incorrect behavior." ; <---
EndIf
ThsLng = #MyConstantB
If (ThsLng = #MyConstantB)
Debug "Correct behavior." ; <---
Else
Debug "Incorrect behavior."
EndIf
Perhaps hexadecimal constants should permit a suffix, such as "L", to distinguish longword and quadword constants.
Negative Longword Constants Specified Via Hexadecimal
Re: Negative Longword Constants Specified Via Hexadecimal
No Bug
Both constant have a different value.
For comparison operations with different types (byte, word, long, quad) this must also be taken into account, since the comparison operations always use integers. Thus under X64 as Quad.
Before the comparison the value Long (Signed) is loaded as Quad (Signed), so that it does not lose its sign, which is correct.
The values must therefore be filtered.
Both constant have a different value.
For comparison operations with different types (byte, word, long, quad) this must also be taken into account, since the comparison operations always use integers. Thus under X64 as Quad.
Before the comparison the value Long (Signed) is loaded as Quad (Signed), so that it does not lose its sign, which is correct.
The values must therefore be filtered.
Code: Select all
EnableExplicit
#MyConstantA = $81010000
#MyConstantB = -2130640896 ;(same value in decimal notation)
Debug Hex(#MyConstantA, #PB_Quad)
Debug Hex(#MyConstantB, #PB_Quad)
Define.l ThsLng
ThsLng = #MyConstantA
Debug ThsLng
Debug #MyConstantA
If ((ThsLng & $FFFFFFFF) = #MyConstantA)
Debug "Correct behavior."
Else
Debug "Incorrect behavior." ; <---
EndIf
ThsLng = #MyConstantB
Debug ThsLng
Debug #MyConstantB
If (ThsLng = #MyConstantB)
Debug "Correct behavior." ; <---
Else
Debug "Incorrect behavior."
EndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Negative Longword Constants Specified Via Hexadecimal
Yes, a defect. Try:
#MyConstantA = $81010000
#MyConstantB = -2130640896 ;(same value in decimal notation)
Debug Hex(#MyConstantA, #PB_Long)
Debug Hex(#MyConstantB, #PB_Long)
YOU ARE REINFORCING MY POINT! A longword constant defined via hexadecimal notation does not behave the same as a longword constant defined in decimal notation. There is no documentation which states that the radix used in the definition of a constant affects its behavior.
This behavior, in fact, leads to numerous seeming bugs. Consider that many Windows constants are defined via hexadecimal notation: if the constant is specified via hexadecimal, its behavior will vary based upon compiler bitness.
#MyConstantA = $81010000
#MyConstantB = -2130640896 ;(same value in decimal notation)
Debug Hex(#MyConstantA, #PB_Long)
Debug Hex(#MyConstantB, #PB_Long)
YOU ARE REINFORCING MY POINT! A longword constant defined via hexadecimal notation does not behave the same as a longword constant defined in decimal notation. There is no documentation which states that the radix used in the definition of a constant affects its behavior.
This behavior, in fact, leads to numerous seeming bugs. Consider that many Windows constants are defined via hexadecimal notation: if the constant is specified via hexadecimal, its behavior will vary based upon compiler bitness.
Re: Negative Longword Constants Specified Via Hexadecimal
I'm not reading too much into this but wanted to mention that on PureBasic 5.71 x86 I see:
So anyone commenting with their opinion of whatever is more "correct" should keep this in mind.Correct behavior.
Correct behavior.
Re: Negative Longword Constants Specified Via Hexadecimal
Those who program have to deal with the differences between programs in X86 and X64 and how Purebasic deals with integers.
Constants:
- X86 : 32/64Bit - Depends on how the assignment is used in the program
- X64 : 64bit
Comparison operations with values always with sign.
X86:
Compare operations with Integer/Long values (standard) as 32bit and the constant as 32bit.
Comparison operations with Quad values as 64bit and the constant as 64bit value.
X64:
Comparison operations with integer/quad values as 64bit and the constant as 64bit value.
This is the trap.
Thus it can come to different result between X86 and X64.
Unfortunately you have to pay attention to this yourself. Other compilers give a warning if the types don't match.
[/size]
Constants:
- X86 : 32/64Bit - Depends on how the assignment is used in the program
- X64 : 64bit
Comparison operations with values always with sign.
X86:
Compare operations with Integer/Long values (standard) as 32bit and the constant as 32bit.
Comparison operations with Quad values as 64bit and the constant as 64bit value.
X64:
Comparison operations with integer/quad values as 64bit and the constant as 64bit value.
This is the trap.
Thus it can come to different result between X86 and X64.
Unfortunately you have to pay attention to this yourself. Other compilers give a warning if the types don't match.
Code: Select all
Procedure.q IntToQuad(value)
ProcedureReturn Value
EndProcedure
#c1 = -1
#c2 = $FFFFFFFF
Debug #c1
Debug #c2
Debug Hex(#c1)
Debug Hex(#c2)
lVal.l = -1
qVal.q = #c1
; Long = Long (force)
If lVal = #c1
Debug "equal"
Else
Debug "not equal"
EndIf
; X64: PB force lVal to signed integer (Quad) and compare constant as 64bit value
If lVal = #c2
Debug "equal"
Else
Debug "not equal"
EndIf
; X86: User force lVal to signed quad and PB compare constant as 64bit value
If IntToQuad(lVal) = #c2
Debug "equal"
Else
Debug "not equal"
EndIf
If qVal = #c1
Debug "equal"
Else
Debug "not equal"
EndIf
If qVal = #c2
Debug "equal"
Else
Debug "not equal"
EndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Negative Longword Constants Specified Via Hexadecimal
I agree that the difficulty varies based on the manner in which a constant is used; however, this doesn't make it less of an issue. The behavior isn't documented and is difficult to detect: in the code below, note that the x86 behavior matches the x64 behavior except when the variable is directly compared to the constant.
==============================
==============================
Code: Select all
EnableExplicit
Enumeration tagMyTest $F0010000 Step $10000
#ValA
#ValB
EndEnumeration
#ValC = $F0010000
Define.l ThsLng
; X86 X64
Debug Hex(#ValA, #PB_Long) ; F0010000 # F0010000
Debug Hex(#ValB, #PB_Long) ; F0020000 # F0020000
Debug Hex(#ValC, #PB_Long) ; F0010000 # F0010000
Debug #ValA ; 4026597376 # 4026597376
Debug #ValB ; 4026662912 # 4026662912
Debug #ValC ; 4026597376 # 4026597376
ThsLng = #ValA
If ((ThsLng & ~ #ValA) = #Null)
Debug "Equal" ; Equal # Equal
Else
Debug "Unequal"
EndIf
If (ThsLng = #ValA)
Debug "Equal" ; Equal # Unequal
Else
Debug "Unequal"
EndIf
Re: Negative Longword Constants Specified Via Hexadecimal
In 64-bit this is real different constant values. When PB evaluate an expression it takes the biggest possible output depending of the native type (ie: 32-bit on x86 and 64-bit on x64) unless you specifically set a quad. This is due for perfomance reason and your case is actually correct on x64 and kind of wrong for x86 (because you hit the native type limit).
Re: Negative Longword Constants Specified Via Hexadecimal
I agree that the x86 version produces the less-correct result; however, that doesn't change the picture much. Many Windows constants (of those in common use, at least 60 supplied in the PureBasic definitions) use the high bit of a longword (that is, are negative longwords): when such constants are considered by PureBasic, they are cast as positive quadwords, not as negative longwords. In my initial post, I suggested that such longword constants might benefit from an "L" suffix to avoid the issue.
The behavior is particularly troubling when evaluating return values. For example, an operating system procedure might return a negative longword value to reflect an error. At present, to produce bitness-agnostic code, one must avoid use of a simple equal sign (and instead use the equivalent and-not).
The behavior is particularly troubling when evaluating return values. For example, an operating system procedure might return a negative longword value to reflect an error. At present, to produce bitness-agnostic code, one must avoid use of a simple equal sign (and instead use the equivalent and-not).