This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Compiler fault? (or am I missing something?)

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;
}

Parents
  • Pointers often don't support any random additions/subtractions of integers.

    But next thing is that with a pointer larger than 16 bits on an architecture that have a 16-bit int, the compiler may not support the use of offsets larger than 16-bit.

    But it is quite common for compiler to normally prioritize efficient code by assuming that normal programs wants pointers that may span the available memory but don't need to access any data structure larger than what the processor can efficiently add with a single instruction or 64kB whichever is larger. But that limit may be smaller or larger depending on the instruction set of the target processor. See more below.

    With the segmented pointers in 8086 processors, a large pointer have a 16-bit segment address that (in real mode) spans 1MB because the value is multiplied by 16. And it has a 16-bit offset. And all pointer arithmetic will only work on the 16-bit offset so memset() etc are limited to at most 64kB of data. Most 8086 compilers also implements a huge pointer, where the offset is constantly normalized to a value 0..15, and where pointer arithmetic affects both offset and segment, allowing the pointer to be stepped forward more than 64kB without any offset overflow.

    This link shows the far pointer for C166, and describes that it is not a linear 32-bit number. There are even bits in the offset part that are not used so the offset is limited to 14 bits.
    http://www.keil.com/support/man/docs/c166/c166_ap_farptr.htm

    But in the C166, even the huge pointer is limited. The documentation says it can only address objects up to 64kB in size:
    http://www.keil.com/support/man/docs/c166/c166_ap_hugeptr.htm

    So a program that needs to play with even larger structures needs the xhuge pointer type:
    http://www.keil.com/support/man/docs/c166/c166_ap_xhugeptr.htm

Reply
  • Pointers often don't support any random additions/subtractions of integers.

    But next thing is that with a pointer larger than 16 bits on an architecture that have a 16-bit int, the compiler may not support the use of offsets larger than 16-bit.

    But it is quite common for compiler to normally prioritize efficient code by assuming that normal programs wants pointers that may span the available memory but don't need to access any data structure larger than what the processor can efficiently add with a single instruction or 64kB whichever is larger. But that limit may be smaller or larger depending on the instruction set of the target processor. See more below.

    With the segmented pointers in 8086 processors, a large pointer have a 16-bit segment address that (in real mode) spans 1MB because the value is multiplied by 16. And it has a 16-bit offset. And all pointer arithmetic will only work on the 16-bit offset so memset() etc are limited to at most 64kB of data. Most 8086 compilers also implements a huge pointer, where the offset is constantly normalized to a value 0..15, and where pointer arithmetic affects both offset and segment, allowing the pointer to be stepped forward more than 64kB without any offset overflow.

    This link shows the far pointer for C166, and describes that it is not a linear 32-bit number. There are even bits in the offset part that are not used so the offset is limited to 14 bits.
    http://www.keil.com/support/man/docs/c166/c166_ap_farptr.htm

    But in the C166, even the huge pointer is limited. The documentation says it can only address objects up to 64kB in size:
    http://www.keil.com/support/man/docs/c166/c166_ap_hugeptr.htm

    So a program that needs to play with even larger structures needs the xhuge pointer type:
    http://www.keil.com/support/man/docs/c166/c166_ap_xhugeptr.htm

Children
No data