The standard set by the American National Standards Institute (ANSI) indicates that integer constants (either literals or integer non-pointer variables) may be assigned to pointers, but what happens after that is implementation-defined? That is to say, it is not clear what will happen if you dereference the pointer or perform other operations on it.
You will also notice in the standard that pointers are only considered valid when they point to an object. It is guaranteed that a pointer points to an object if you assign it the address of an object (using the unary & operator) rather than assigning an integer value.
The MPLAB® XC8 compilers perform several optimizations that are based on information obtained from each pointer's target list. These optimizations can be defeated if the information regarding targets is not complete.
Regardless of which compiler you use, always take the address of an object when assigning to a pointer. In some instances, it may be necessary to create a dummy object whose address can be taken, if no other object exists.
The information the compiler needs to fully understand a pointer target is:
- the base address of the target
- the size of the target
- the memory space in which the target lies
- the type of the target
Let's look at special examples where you might be tempted to assign integers to pointers.
Let's say you want to use a pointer to calculate a checksum of all locations in bank 2 data memory (from addresses 110h to 16fh) on a mid-range PIC® device. We assume here that every memory location holds significant value, but that there could be many C objects that reside in bank 2, and we are not sure which object these are. First, create a dummy object that resides at the addresses of interest and in the desired memory space:
The object is made extern so that it does not have memory reserved for it, and being absolute, it can exist "over the top" of other objects in this bank. From this object, the compiler can determine all four of the above attributes. Now you can use this object:
Note the pointer is assigned an address that is derived from a C object.
Note, also, the pointer comparison in the while() statement. The ANSI standard also indicates that addresses may only be compared when they point to the same object. Again, you should compare pointers with the address of some object, not an integer constant cast to be a pointer.
If you wanted to do a similar thing, but with objects in program memory, the procedure is the same. Note that not all devices can directly read their program memory, and may implement program memory which is word-addressable. If arrays are located in this memory, the values read using a pointer will be the data values in the array. You could not use this method to calculate a checksum of the instructions in a block of program memory. You would need to use a Flash read function to do that if they exist for the target device.
Let's say we want to read from address 2000h to 2fffh, and assuming there is no single C object that resides at these addresses, first create a dummy object located both here and in the desired memory space:
Here the const qualifier implies the program memory space. As there are no initial values, this object does not contribute to the output HEX file, and so will not overwrite any other objects.
Now you can use this object:
The compiler does understand the special case of an assignment of zero to a pointer. This is a null pointer, has a special meaning, and is an address that is guaranteed not to point to any object.
If you need to take the address of an object defined in assembly code, write an appropriate C declaration for the assembly object, and then use this C object as the target.