What do I need to do to C code that assigns an integer to a pointer when migrating this code to the XC8 compiler?

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.

© 2020 Microchip Technology, Inc.
Notice: ARM and Cortex are the registered trademarks of ARM Limited in the EU and other countries.
Information contained on this site regarding device applications and the like is provided only for your convenience and may be superseded by updates. It is your responsibility to ensure that your application meets with your specifications. MICROCHIP MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO THE INFORMATION, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, PERFORMANCE, MERCHANTABILITY OR FITNESS FOR PURPOSE. Microchip disclaims all liability arising from this information and its use. Use of Microchip devices in life support and/or safety applications is entirely at the buyer's risk, and the buyer agrees to defend, indemnify and hold harmless Microchip from any and all damages, claims, suits, or expenses resulting from such use. No licenses are conveyed, implicitly or otherwise, under any Microchip intellectual property rights.