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
  • When you quoted from that book, did you also notice this part:
    "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."

    On one hand, the book is correct. But on the other hand, it isn't. The language standard does not contain any rule that says that the integer 6 (when cast into a pointer) will point to the 6th byte of any memory region. The assign may just as well result in an invalid pointer that either addresses air or results in an exception by the processor. The standard does not require the compiler to perform any magic translations when you typecast between integer and pointer.

    The language standard, §6.3.2.3 bullet 5 says:
    "An integer may be converted to any pointer type. Except as previously specified, the
    result is implementation-defined, might not be correctly aligned, might not point to an
    entity of the referenced type, and might be a trap representation.56"

    And bullet 6 says:
    "Any pointer type may be converted to an integer type. Except as previously specified, the
    result is implementation-defined. If the result cannot be represented in the integer type,
    the behavior is undefined. The result need not be in the range of values of any integer
    type."

    The language standard, §6.5.6 bullet 9 talks about the situation where the subtraction between two pointers gives a result too large to fit in ptrdiff_t (a signed integer type), then the result is undefined.

    But 6.5.6 also cover the situation where the addition of an integer to a pointer to an array element (or one step past the last array element) results in a pointer that isn't pointing to one element in the array or one step past last element.

Reply
  • When you quoted from that book, did you also notice this part:
    "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."

    On one hand, the book is correct. But on the other hand, it isn't. The language standard does not contain any rule that says that the integer 6 (when cast into a pointer) will point to the 6th byte of any memory region. The assign may just as well result in an invalid pointer that either addresses air or results in an exception by the processor. The standard does not require the compiler to perform any magic translations when you typecast between integer and pointer.

    The language standard, §6.3.2.3 bullet 5 says:
    "An integer may be converted to any pointer type. Except as previously specified, the
    result is implementation-defined, might not be correctly aligned, might not point to an
    entity of the referenced type, and might be a trap representation.56"

    And bullet 6 says:
    "Any pointer type may be converted to an integer type. Except as previously specified, the
    result is implementation-defined. If the result cannot be represented in the integer type,
    the behavior is undefined. The result need not be in the range of values of any integer
    type."

    The language standard, §6.5.6 bullet 9 talks about the situation where the subtraction between two pointers gives a result too large to fit in ptrdiff_t (a signed integer type), then the result is undefined.

    But 6.5.6 also cover the situation where the addition of an integer to a pointer to an array element (or one step past the last array element) results in a pointer that isn't pointing to one element in the array or one step past last element.

Children
  • "What exactly is the compiler doing in the situation where the value is not computed as I expect it to be. What interaction between the XC161's segmented addressing and the compiler's casting of POINTER to ULONG is impacting unexpectedly on the computation?"

    So have you looked at the xhuge pointer type? Your code are just using the default pointer type for your memory model, and you haven't told us what that memory model is. The alternative is that you perform the required integer arithmetic to create the binary representation of good pointers of the pointer type you want to use. That may include a workaround for 14-bit offsets stored in 16 bits with 2 bits zeroed.