Using the latest Keil C compiler (V7.00) Executing on an Infineon XC161CJ-16F This code appears to produce the wrong result.
At the "if" statement I expect v1 to equal v3 and for the main function to return 0 (I don't actually want to use the return value, its just a mock up piece of code). However, at the "if" statement, the value of v1 is 0x1234 and the value of v3 is 0xB1234.
Can anyone explain why?
typedef unsigned long ULONG; typedef unsigned short USHORT; typedef BYTE * POINTER; POINTER v1,v2,v3,v4; ULONG temp_ptr; int main(void) { v1 = (POINTER)0; v2 = (POINTER)0x0B1234; v1 += (ULONG)v2; // This assigns 0x1234 to v1, I think it should assign 0xB1234 v3 = (POINTER)0; v4 = (POINTER)0x0B1234; temp_ptr = (ULONG)v3; v3 = temp_ptr+v4; // This statement assigns 0xB1234 to v3 correctly. if ( v1!=v3 ) return -1; else return 0; }
Firstly, I'd like to say thanks Per Westermark, I really appreciate the time and patience you have shown trying to help me work through this problem.
@Per Westermark
As you can see, your recent post does not sum up your problem since you are there describing a completely different concept - no pointer added. Just two ways of adding an integer.
Ahh crap! I was having a bad day yesterday. You are absolutely correct. I was just trying to simplify the problem and got the simplification wrong, please ignore it. The originally posted code is what I should be referring to.
unless you can find a specific document claiming exactly the limitations to Keils pointer support, you really are busy in the undefined domain.
This is from the Keil documentation (my emphasis): The C166 compiler and the L166 Linker/Locater handles all the CPU addressing modes for you. Therefore the different CPU address calculations are totally transparent to the C programmer. <snip> The huge and xhuge pointer values are representing directly physical memory addresses.
By the way - why do you claim to use the xhuge memory model? You don't need xhuge as a general memory model unless you want every single pointer to be able to span large data ranges. Why would there even be huge or far pointers if xhuge would be a good choice for general use?
I incorrectly thought my app was using the XLarge memory model and that the pointers by default were therefor xhuge pointers. That is not the case, my app is using the HLarge memory model and the pointers by default are therefor huge.
I have logged the fault with KEIL support, maybe they can shed some light on it. But if you have any more suggestions, I'd like to know, thanks.
-------------------------------------------------------------
If I change the code line:
typedef BYTE * POINTER; // that should have been char not BYTE by the way
to
typedef char xhuge * POINTER;
then the code works as expected.
That confirms that there is a difference in the way the compiler handles huge and xhuge pointers. However, it still does not explain why the code does not produce the same pointer value in the two different calculations.
For example, if huge pointers were only supposed to cast the low 16 bits when cast to an integer, then both pointer calculations should have resulted in 0x1234. If huge pointers were supposed to cast the full 32 bit address when cast to an integer, then both pointer calculations should have returned 0xB1234.
I'm not trying to argue that xhuge or huge should behave in a certain way (although I would like to know for sure how they are implemented to behave), I am merely trying to find out why doing the calculation one way yields a different result to doing it another way.
Regards Paul