Special Pointer Targets

Pointers and integers are not interchangeable. Assigning an integer to a pointer will generate a warning to this effect. For example:

const char * cp = 0x123;  // the compiler will flag this as bad code

There is no information in the integer constant, 0x123, relating to the type, size or memory location of the destination. There is a very good chance of code failure when dereferencing pointers that have been assigned integer addresses, particularly for PIC devices that have more than one memory space.

Always take the address of a C object when assigning an address to a pointer. If there is no C object defined at the destination address, then define or declare an object at this address which can be used for this purpose. Make sure the size of the object matches the range of the memory locations that are to be accessed by the pointer.

For example, a checksum for 1000 memory locations starting at address 0x900 in program memory is to be generated. A pointer is used to read this data. You can be tempted to write code such as:

const char * cp;
cp = 0x900;  // what resides at 0x900???

and increment the pointer over the data.

However, a much better solution is this:

const char * cp;
extern const char inputData[1000] __at(0x900);
cp = inputData;
// cp is incremented over inputData and used to read values there

In this case, the compiler can determine the size of the target and the memory space. The array size and type indicates the size of the pointer target, the const qualifier on the object (not the pointer) indicates the target is located in program memory space. Note that the const array does not need initial values to be specified in this instance, see Const Type Qualifier and can reside over the top of other objects at these addresses.

If the pointer has to access objects in data memory, you need to define a different object to act as a dummy target. For example, if the checksum was to be calculated over 10 bytes starting at address 0x90 in data memory, the following code could be used.

const char * cp;
extern char inputData[10] __at(0x90);
cp = inputData;
// cp is incremented over inputData and used to read values there

No memory is consumed by the extern declaration and this can be mapped over the top of existing objects.

User-defined absolute objects will not be cleared by the runtime startup code and can be placed over the top of other absolute variables.

Take care when comparing (subtracting) pointers. For example:

if(cp1 == cp2)
    ; // take appropriate action

The C standard only allows pointer comparisons when the two pointers’ addresses are of the same object. One exception is that the address can extend to one element past the end of an array.

Never compare pointers with integer constants as that is even more risky, for example:

if(cp1 == 0x246)
    ; // take appropriate action

A null pointer is the one instance where a constant value can be assigned to a pointer and this is handled correctly by the compiler. A null pointer is numerically equal to 0 (zero), but this is a special case imposed by the C standard. Comparisons with the macro NULL are also allowed.