Keil Logo

Pointer Conversions

The C251 compiler can convert the memory types of pointers. Pointer conversions can be forced by explicit program code using type casts or can be coerced by the compiler. A generic pointer is identical to a near * pointer definition for the TINY or XTINY memory model. For all other memory models a generic pointer is the same as a far * pointer definition.

The C251 compiler converts a memory specific pointer into a generic pointer when the memory specific pointer is passed as an argument to a function which requires a generic pointer. This is the case for C251 run time library functions such as printf, sprintf, and gets which use generic pointers as arguments. For example:

extern int printf (void *format, ...);

extern int myfunc (void near *p, int data *dq);

int data *dp;
const char near *fmt = "value = %d | %04XH\n";

void debug_print (void)  {
  printf (fmt, *dp);              /* fmt is converted */
  myfunc (fmt, nx);                 /* no conversions */
}

In the call to printf, the argument fmt which represents a 2 byte near pointer is automatically converted or coerced into generic pointer. This is done because the prototype for printf requires a generic pointer as the first argument. Depending on the memory model the size of a generic pointer is 2 bytes or 4 bytes.

Note

  • In the memory models TINY or XTINY it is not possible to access memory locations above 0x010000 with the standard C251 run time library functions. Therefore, the format string to the printf must be declared as const char near. If you declare the format string as char code (as is done in the C51 programs) the printf only works in the SMALL, XSMALL or LARGE memory model.

Pointer conversion are mostly done by extending or truncating the high part of the pointer, since the address space is viewed as a linear entity. The following table details the process involved in converting pointers.

Conversion Type Description
far * to code * The low order word (2 bytes) of the far * is used as offset. The high order word is discarded.
far * to data *
far * to idata *
The low order byte of the far * is used as offset.
far * to near * The low order word (2 bytes) of the far * is used as offset.
far * to xdata * The low order word (2 bytes) of the far * is used as offset.
far * to pdata * The low order byte of the far * is used as offset.
code * to far * The high order word of the far * is set to the code base (default 0xFF). The 2 byte offset of the code * is used.
idata * to far *
data * to far *
The high order word of the far * is set to 0x00 for idata / data.
The 1 byte offset of the idata * / data is converted to an unsigned int and used as low-order word.
near * to far * The high order word of the far * is set to 0x00 for near.
The 2 byte offset of the near * is used as low-order word.
xdata * to far * The high order word of the far * is set to xdata base (default 1).
The 2 byte offset of the xdata * is used as low-order word.
pdata * to far * The high order word of the far * is set to xdata base (default 1).
The high order byte of the offset is set to the pdata page.
The 1 byte offset of the pdata * is used as the low-order byte of the offset.
near * to data *
near * to idata *
Only the low-order byte of the near * pointer is used as offset.
data * to near *
idata * to near *
The 1 byte offset of the idata * / data * is converted to an unsigned int and used as offset for the near * pointer.

All pointer conversions not listed in this table are illegal and generate a WARNING message at compile time.

The following example listing illustrates a few pointer conversions.

        stmt level  source
   1        int *p1;           /* generic ptr (3 bytes) */
   2        int xdata *p2;     /* xdata ptr (2 bytes) */
   3        int near *p3;      /* near ptr (1 byte) */
   4        int code *p4;      /* code ptr (2 bytes */
   5
   6        void pconvert (void) {
   7   1    p1 = p2;           /* xdata* to generic* */
   8   1    p1 = p3;           /* near* to generic* */
   9   1    p1 = p4;           /* code*  to generic* */
  10   1
  11   1    p4 = p1;           /* generic* to code* */
  12   1    p3 = p1;           /* generic* to near* */
  13   1    p2 = p1;           /* generic* to xdata* */
  14   1
  15   1    p2 = p3;           /* near* to xdata* (WARNING) */
*** WARNING 259 IN LINE 15 OF P.C: pointer: different mspace
  16   1    p3 = p4;           /* code*  to near* (WARNING) */
*** WARNING 259 IN LINE 16 OF P.C: pointer: different mspace
  17   1    }
  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.