Inconsistency in Pointer Assignments?


having read Kem’s thread about “Pointer math”, I started to play with that a bit because it can be quite handy at times.
What I stumbled upon was the fact, that:

dim bPtr as Ptr = + Ptr(Offset) on my Win7 64-Bit Xojo 2.1 machine seems to behave different than
dim aPtr as Ptr =
aPtr = aPtr + Ptr(Offset)

From what I see in the debugger I suspect, that the term Ptr(Offset) in the first line evaluates to the contents of memory location , whereas in line 3 it evaluates to .
My questions are:
a) is it meant to behave this way and I am just to stupid to see why
b) how safe would it be to rely on aPtr = aPtr + Ptr(Offset) evaluating as expected (the way it does now) in the future?

Below is a short sample I used to to play with this:

dim aMem as new MemoryBlock(9) aMem.UInt32Value(1) = 123456 dim aPtr as Ptr = aMem aPtr = aPtr + Ptr(1) dim bPtr as Ptr = aMem + Ptr(1) if aPtr.UInt32(0) = 123456 then msgbox "aPtr works Right" if bPtr.UInt32(0) = 123456 then msgbox "bPtr works Right"

You’ve found a wonderfully painful edge case. The short explanation is that in addition to converting to/from a Ptr, MemoryBlock also has an Operator_Add. The assignment to ‘aPtr’ is a direct conversion to Ptr via Operator_Convert. The assignment to ‘bPtr’ is more complex: the ‘Ptr(1)’ gets converted to a MemoryBlock, Operator_Add gets invoked on ‘aMem’ with the converted MemoryBlock, and then the result of that is converted to a Ptr via Operator_Convert.

Thanks a lot for the fast response.

If I get this right, the problem with bPtr is, that aMem being the first operator is of a different datatype causing unexpected conversions. So to summarize:

dim bPtr as Ptr = aMem + Ptr(1) ’ gives unexpected result
dim bPtr as Ptr = Ptr(1) + aMem ’ gets rejected by the compiler

dim bPtr as Ptr = ctype( aMem, Ptr ) + Ptr(1) = Ptr(1) + ctype( aMem, Ptr ) = expected result

So would you say that I can rely on the latter in my programs?

Besides maybe some hint on this in the LR would be a good idea.

The key point, and it affects other situations like integer vs. floating point addition, is: Xojo evaluates the right hand side of an assignment independently of the left hand side. In other words, the right hand side is evaluated and any conversions are performed without taking into account the type of the variable receiving the result. There are some very good reasons for doing it this way, but it does introduce some interesting edge cases. For example, suppose you have a statement like

Int64 = Integer * Integer

The values of the right side will be elevated as Integer and the result will be expressed as an Integer value and then that result will be converted to an Int64. The result could overflow, but that happens before it is converted to an Int64. So you could get a very different result than

Int64 = Int64 * Integer

It’s just a gotcha that you have to take into account in your code.

Thanks to both of you for the answers.

Yes, it’s correct, I had not thought about the Operator_Add in the LR so thanks for the hint.
And yes, the reason for Operator_Add getting executed lies in the way Xojo evaluates assignments.

However thinking more about this I wonder when exactly does the right hand side get evaluated indepently of the left?

Ptr = Memoryblock + Ptr( integer ) ’ Right hand side evaluated to memoryblock and result converted to Ptr
Int64 = int8 * int8 ’ right hand side evaluated to int8 and result converted to Int64
Double = int8 / int8 ’ Oops, this seems different ( will NOT deliver the result of integer division)
int64 = int8 ^ int8 ’ different too ( will NOT deliver overflown int8 value)

So is there a rule or a list for this? Thanks in advance