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; }
Using the ARM complier, this code behaves according the OP's comments.
You pretty much answered your own question there. The result of that code changes just because you switch compilers --- because it's result is undefined.
The fact that an ARM's address space is naturally 32bit, while that of a C166 is basically 16-bit, quite probably caused the OP's expectations to be broken in the first place.
@Hans-Bernhard Broeker
I think that Tamir Michael may have been saying the ARM compiler does exactly what the XC161 compiler does - at least that's how I read it. I've asked for clarification.
I too believe it is the segmented addressing of the XC161 addressing that is causing the problem. However, I think the compiler is not allowing for that segmentation the way I expect it to.
By the way, I disagree with you that it is undefined. I know what the target hardware is, I know what the target CPU architecture is. I am not writing "portable" code to run on multiple disparate architectures. C is a language that was/is designed to access the hardware directly, otherwise it is a pretty pointless language with which to develop embedded systems.
For example, this taken from here: publications.gbdirect.co.uk/.../pointers.html
The only values that can be assigned to pointers apart from 0 are the values of other pointers of the same type. However, one of the things that makes C a useful replacement for assembly language is that it allows you to do the sort of things that most other languages prevent. Try this:
int *ip; ip = (int *)6; *ip = 0xFF;
What does that do? The pointer has been initialized to the value of 6 (notice the cast to turn an integer 6 into a pointer). This is a highly machine-specific operation, and the bit pattern that ends up in the pointer is quite possibly nothing like the machine representation of 6. After the initialization, hexadecimal FF is written into wherever the pointer is pointing. The int at location 6 has had 0xFF written into it—subject to whatever ‘location 6’ means on this particular machine.
Regards Paul
However, I think the compiler is not allowing for that segmentation the way I expect it to.
And that's because those epxectations are wrong. Not the compiler.
C is a language that was/is designed to access the hardware directly, otherwise it is a pretty pointless language with which to develop embedded systems.
And the way C does those things is by leaving them undefined at the language level. That leaves implementors exactly the kind of freedom they may need to perform all those less-than-portable things efficiently, and without immediately having to resort to utterly unportable extensions of the language itself. In way, C gives you just enough rope to hang yourself.
Yes of course. I seem to assume lately that the default architecture is "ARM"...