I’m getting a little confused about data types of literal numbers in Xojo. I have something like this:
BS.Position = UInt32Number + 8
BS is a BinaryStream, Position is UInt64. When UInt32Number gets above the 2GB limit (where it exceeds being signed), the Position value doesn’t get set (with the code line above) to what I would think UInt32Number + 8 would be.
But if I changed the 8 literal to a UInt32 variable, it works. It’s like the 8 literal demotes the equation to something signed or whatever. I can this: UInt32(8) and it works as well. It sure would be a bummer if I can’t use literals accurately if I’m using them with UInt32 variables.
Can someone clarify this to me?
“8” is classified as an Int32, and my results are consistent no matter if I use a literal or variable. The problem is, if you have 4-byte values on the right side of the equation, the result will be a 4-byte value coerced into an 8-byte variable.
A simple test to see what the compiler considers the literal to be:
dim arr() as String = Array( 8 )
The “type mismatch” compiler error will tell you what the compiler considers “8” to be.
Sorry, I missed that you are within the boundaries of an Int32. But my results are correct regardless.
By the way, you can force the literal to a certain type with CType:
l = l + CType( 8, UInt64 )
I still don’t understand. Basically the situation is:
UInt64 = UInt32 + Int32
In my situation, for a value of UInt32 being slightly over 2GB (around 2183776988) and Int32 being the literal 8, I was getting UInt64 being 4 less than what it should have been. Your explanation doesn’t seem to explain that. Wouldn’t the Int32 be promoted to UInt32, but even not, how does this finagle with the bits in question? Int32 isn’t negative.
Oh no - here we go again :). Unfortunately, RS / Xojo does not coerce (maybe cast is a better term here) values to the size of the largest value but rather the size of the smallest.
Therefore, when you add 2 32bit values, you must cast them to 64 bit values before you add them to get a 64 bit answer.
I see the effect you’re talking about. In your example, what’s happening is that the right is being processed as Int32, then converted to UInt64, giving us really bizarre results.
You’re better off switching your UInt32 on the right to an UInt64, then using CType to specify the literal as UInt64 too.
[quote=69345:@Tim Jones]Oh no - here we go again :). Unfortunately, RS / Xojo does not coerce (maybe cast is a better term here) values to the size of the largest value but rather the size of the smallest.
It computes a common type that it uses for intermediate results - mostly it computes the “largest” common type it requires and then assigns that to the destination
So who’s right - TIm or Norman?
If Norman is correct (and that’s what I think SHOULD happen) this should be working, but it’s not.
They’re both correct. As Norman says, it normalizes to the largest common type, which is usually, as Tim observes, the smaller type. Between an UInt32 and an Int32, the largest common type is Int32. You can override this, of course.
I think the significant detail i was looking for what Tim Jones said - Adding two types together, it doesn’t promote the lesser types but demotes the larger types. I don’t want to rate your help, but saying “between an UInt32 and an Int32, the largest common type is Int32” seems like a confusing way to say it, because UInt32 is larger than Int32 (in positive values, at least). Or perhaps I don’t know what you mean by “common type”.
For my example, I don’t think the UInt64 return value makes any difference, the issue is that I was adding a Int32 (literal) to a UInt32, and internally Xojo demoted the UInt32 to a Int32. But then why did I get a large >2GB positive value (it was only off by 4)? If the >2GB UInt32 got demoted, wouldn’t that be either a smaller positive number (since it was slightly above 2GB) or a highly negative number?
This is opposite of the normal C/C++ compilers in VS and XCode, they promote integers, not demote, correct?
So… since integer literals are always signed, working with any unsigned datatype, one must be careful to explicitly unsign any literal that is used, with Xojo.
I think a good way of seeing this is:
Dim ThisNum As UInt32
Dim rtBool As Boolean
ThisNum = 3000000000 // 3 billion
rtBool = (ThisNum > 0) // rtBool will be False
Seems crazy to have to cast literals all the time with (mainly) UInt32, but I guess I haven’t been around the block enough. =)
The type of the 8 literal is Int32 (signed int 32)
The type of UInt32Number is - obviously - Uint32
The common type between them is computed to be Int32 - which in the case where the Uint32 has a value > the max for an Sint32 you could have issues (i.e. 2147483648 and up)
That seems to be the case here
It’s not intended to be a demotion - it just happens to work that way & fixing this could break a lot of stuff with the current compiler